Question: Create a div with aspect ratio 1:1 knowing only its height in percentage

Question

Create a div with aspect ratio 1:1 knowing only its height in percentage

Answers 4
Added at 2016-12-30 15:12
Tags
Question

I was wondering if you can help me with this. I have a div (in white) where I need to put two circular buttons (in green) on the borders. Everything should be done with CSS. It should look like this: Screenshot

Now, the thing is that I don't know the size of the white div, and I won't know it at the time of creation, because it will get added to the DOM afterwards. All I know is that the white div has a percentage width and height relative to its future parent. So, at the time of creation, since it's not yet added, any calls to width(), height() or its css values won't work. I've seen all those snippets that tell you how to make a div with a fixed aspect ratio. I need this now, I need the button to be 1:1, but all I know about the dimensions, is that it has to be 100% of the height of the white div (and therefore, its width should be equal as its height). All the examples I've seen assume that you know the width and to make the height keep the ratio. In my case, what I know is the height (100%) and I want the width to adapt. I have no idea how to achieve this.

This is my snippet:

body{
  background-color: #DCDCDC;
}
.container {
  width: 50%;
  height: 7%;
  background: white;
  border-radius: 20px;
  position: absolute;
}
.arrow {
  background: green;
  border-radius: 20px;
  height: 100%;
  position: absolute;
}
.arrow:after{
  content: "";
  display: block;
  padding-right: 100%;
}
.arrow:last-child {
  right: 0;
}
<div class="container">
  <div class="arrow"></div>
  <div class="arrow"></div>
</div>

https://jsfiddle.net/7bxecL9m/

If you know how can I do this without entering any fixed value (jQuery use is of course valid), I'd really appreciate it.

Thanks.

Answers
nr: #1 dodano: 2016-12-30 16:12

Why not doing a fixed width in percent for your arrow :

.arrow {
  background: green;
  border-radius: 20px;
  height: 100%;
  position: absolute;
  width: 10%;
}
nr: #2 dodano: 2016-12-30 16:12

body{
  background-color: #DCDCDC;
}
.container {
  width: 50%;
  height: 7%;
  background: white;
  border-radius: 20px;
  position: absolute;
}
.container:after,.container:before{
  content: " ";
  display: block;
  padding: 4%;
  z-index: 999;
  top: 0;
  position:absolute;
  background: green;
  border-radius: 50%;
}
.container:before {
  left: 0;
}
.container:after{
  right: 0;
}
<div class="container">
</div>

You can achieve using before and after CSS pseudo selectors. You check this Example.

nr: #3 dodano: 2016-12-30 17:12

There are many variables here:

  • Since container's height is % and circle radius is px units, one is static and the other one will resize.
  • The only way to preserve 1:1 with just html/css, considering the container's height % will resize circle's height as well, would be to isolate circle's div width & height to something static like px units.
  • Now, since you said no fixed dimensions, the only thing I can think of is to comment .arrow's 100% height, to prevent resizing other than 1:1, and nesting a div inside .arrow to restrain 1:1 with static units (ideally impacting .arrow directly would be less code but if you don't want/can't set them on that element, maybe you consider this).

If you want the circle to remain circular as the content expands, you need to dynamically adjust the height to match the width. You could use Javascript to achieve this, but your border-radius is tied to container's in px static units, since container will always be bigger something like border-radius: 50% wouldn't work for both, 50% radius of circle would never match 50% of container's (that is, if you care about radius alignment).

body {
  background-color: #DCDCDC;
}
body,
html {
  height: 100%;
}
.container {
  width: 50%;
  height: 37%;
  background: white;
  border-radius: 20px;
  position: relative;
}
.arrow {
  background: green;
  border-radius: 20px;
  /*height: 100%;*/
  position: absolute;
  overflow: hidden;
}
.bLimit {
  height: 40px;
  width: 40px;
  line-height: 40px;
}
.arrow:after {
  content: "";
  display: block;
  padding-right: 100%;
}
.arrow:last-child {
  right: 0;
}
<div class="container">
  <div class="arrow">
    <div class="bLimit">button overflow</div>
  </div>
  <div class="arrow">
    <div class="bLimit">button</div>
  </div>
</div>

nr: #4 dodano: 2016-12-30 19:12

There is a posibility to get this result using a image (that won't show) of the required ratio.

In this case, the ratio is 1:1 so we will use an image of 50px (but it can be any size)

.container {
  width: 300px;
  height: 20px;
  border: solid 1px blue;
  margin: 40px;
  position: relative;
}
.container:nth-child(2) {
  height: 40px;
}
.container:nth-child(3) {
  height: 60px;
}
.arrow {
  height: 100%;
  background-color: red;
  opacity: 0.5;
  position: absolute;
  border-radius: 50%;
  transform: translateX(-50%);
}
.arrow:last-child {
  right: 0px;
  transform: translateX(50%);
}
img {
  height: 100%;
  opacity: 0;
}
<div class="container">
  <div class="arrow">
    <img src="https://placehold.it/50x50">
  </div>
  <div class="arrow">
    <img src="https://placehold.it/50x50">
  </div>
</div>
<div class="container">
  <div class="arrow">
    <img src="https://placehold.it/50x50">
  </div>
  <div class="arrow">
    <img src="https://placehold.it/50x50">
  </div>
</div>
<div class="container">
  <div class="arrow">
    <img src="https://placehold.it/50x50">
  </div>
  <div class="arrow">
    <img src="https://placehold.it/50x50">
  </div>
</div>

Source Show
◀ Wstecz