Pure CSS Solution - Square Elements? [duplicate]

2019-01-22 19:38发布

This question already has an answer here:

If I have a <div> with a relative width (such as width: 50%), is there a simple way to make it have the same width as it does height without resorting to JavaScript?

6条回答
霸刀☆藐视天下
2楼-- · 2019-01-22 20:05

Not with relative units like %, because they would be calculated relative to a container element. But it's possible to make an element square if you use units like px or em to set both dimensions.

查看更多
冷血范
3楼-- · 2019-01-22 20:13

No, and Yes (Kinda)

Okay, so the short answer is "no," not possible. The long answer is, "yes," given certain constraints and concessions (i.e. extra html markup, and limitations on what can be done).

Given this CSS:

.square {
    position: relative;
    margin: 20px;
    display: inline-block; /* could be float */
    overflow: auto; /* UPDATE: if content may overflow square */
}
.sq-setter-w {
    width: 100%;
    height: auto;
    visibility: hidden;
}
.sq-setter-h {
    width: auto;
    height: 100%;
    visibility: hidden;
}
.sq-content {
    position: absolute;
    z-index: 1;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
}

With this HTML:

<div class="square" style="width: 200px">
    <img src="http://dummyimage.com/50x50/000/fff.gif&text=50x50" class="sq-setter-w"/>
    <div class="sq-content">Here is content</div>
</div>
<div class="square" style="height: 100px">
    <img src="http://dummyimage.com/50x50/000/fff.gif&text=50x50" class="sq-setter-h"/>
    <div class="sq-content">Here is content</div>
</div>
<div class="extrawrapper">
<div class="square" style="width: 200px">
    <img src="http://dummyimage.com/50x50/000/fff.gif&text=50x50" class="sq-setter-w"/>
    <div class="sq-content">Here is content</div>
</div>
</div>
<div class="extrawrapper">
<div class="square" style="height: 100px">
    <img src="http://dummyimage.com/50x50/000/fff.gif&text=50x50" class="sq-setter-h"/>
    <div class="sq-content">Here is content</div>
</div>
</div>

You can get it to do what this fiddle shows.

The keys are:

  1. The image used needs to be a square image, as it is driving the proportional sizing (the img element is the only element that can do such proportional work, as it can base its size off the proportion of the image itself).
  2. You have to know if you are going to set the width or the height so that you can set the image class correctly to size it. Optionally, set the width or height on the img itself, then you don't need to worry about setting a class to the 100% value. My demo was assuming that you set the size on the wrapper div (my .square class).
  3. To get the div to collapse around the img which is driving the proportional sizing you need to set display: inline-block or a float on the div (as noted in the css above).
  4. Because of #3, if you want that div to act more "block-like" you need to give them an extra wrapper div like the third and fourth ones show.

Obviously, there is a lot of extra mark-up involved in this solution. So in many ways it is better to say "just use javascript," but I did want to prove that it could be done (at least in some cases) purely with HTML and CSS.

Update: To Show Flexible Sizing Possibility

See this fiddle for percentages driving the size, with this html example (width set to 30%):

<div class="square" style="width: 30%">
    <img src="http://dummyimage.com/50x50/000/fff.gif&text=50x50" class="sq-setter-w"/>
    <div class="sq-content">Here is content</div>
</div>
查看更多
乱世女痞
4楼-- · 2019-01-22 20:19

A native JS approach in response to @Dave comment on @praveen-kumar answer:

var squareElement = function(el) {
    el.style.height = el.offsetWidth + 'px';
}

and use it anywhere

squareElement(document.querySelector('your-selector'));
查看更多
戒情不戒烟
5楼-- · 2019-01-22 20:26

This cannot be done with CSS alone. Using jQuery you can achieve this by doing

var chld = $('.child').width();
$('.child').css({'height':chld+'px'});

Check working example at http://jsfiddle.net/4Jnfq/


A CSS only solution can be found here on the last "Resize with content" update.
Although it applies for circles, you can remove the border-radius: 50% to make it work for squares.

查看更多
别忘想泡老子
6楼-- · 2019-01-22 20:28

It is actually possible to achieve it with this neat trick i found at this blog

#square {
   width: 100%;
   height: 0;
   padding-bottom: 100%;
}

Hope that helps

查看更多
Animai°情兽
7楼-- · 2019-01-22 20:30

I needed to achieve something similar today and had the same idea with the image. I wanted to check other possibilities and google led me here.

...you don't really need an image src. you can simply use a hash if you want a square. It saves a http request.

If you want to get different aspect ratio you should use a src though. If you want to have a ratio of 16:9 the image should be 16px wide and 9px high (go as small as possible)


Comparing both techniques (see other answers in this thread)

img vs. padding-bottom

Here's a fiddle to show how much more compatible the img version is (can easily handle pxvalue too (an interval will resize the "square" each second)

If you use percentage values both techniques can achieve the same result but the padding version does not need the extra markup (<img src="#"/>)


Conclusion:

Depending on the implementation each technique has it's pros and contras.


HTML

<div class="floater">
    <div class="square square_noImg">
        <div class="inner">Hey blue you look totally squared</div>
    </div>
    <div class="square square_img">
        <img src="#"/>
        <div class="inner">Hey red you seem off</div>
    </div>
</div>

CSS

.floater {
    font-size: 0;
}
.square {
    position: relative;
    display: inline-block;
    width: 100px;
    margin: 0 5px; 
}
.square_noImg {
    padding-bottom: 100px;
    background: red;
}
.square_img {    
    background: blue;
}
img{
    width: 100%;
    height: auto;
    border: 0;
    visibility: hidden;
}
.inner {
    position: absolute;
    top: 10%;
    right: 10%;
    bottom: 10%;
    left: 10%;
    background: white;
    font-size: 14px;
    text-align: center;
    overflow: hidden;
    padding: 10px 5px;
}
查看更多
登录 后发表回答