How to always center a flexible square in viewport with pure CSS? - css

I know this question: Height equal to dynamic width (CSS fluid layout)
But I want more!! I want a flexible container which has always the aspect ratio of a square but with max-height and max-width of 100% of the page (the window element) and on the top of it is always vertically and horizontally centered.
Like this:
// Container matches height of the window
// container-height = 100%; container-width = absolute-container-height
-page/browser-window-
- ####### -
- #cont-# -
- #ainer# -
- ####### -
---------------------
// container matches width of the window
// container-width = 100%; container-height = absolute-container-width
--page---
- -
- -
-#######-
-#######-
-#######-
-#######-
- -
- -
---------
Is it possible to achieve this with pure css (and even better cross-browser)?
Edit:
I know there is calc() for css3, but due to the poor mobile browser-support, I don't want to use it.
Edit2:
Seems like, I didn't make myself clear enough. I need height and width of the wrapper to match the height OR the width of the window, depending on which is smaller.The square-container should never exceed the smaller value of the window-height/width.
This is, how it would be done with jQuery:
// container/#main-wrapper has top: 50%, left: 50%, position: absolute via css
$(window).resize(function () {
var $ww = $(window).width();
var $wh = $(window).height();
if ($ww > $wh) {
$('#main-wrapper').css({
height: $wh,
width: $wh,
marginTop : ($wh / 2) * -1,
marginLeft : ($wh / 2) * -1
});
} else {
$('#main-wrapper').css({
height: $ww,
width: $ww,
marginTop : ($ww / 2) * -1,
marginLeft : ($ww / 2) * -1
});
}
});

I finally figured it out. The magic ingredients are the view-port units.
Given this html structure:
.l-table
.l-table-cell
.square
You can use this css (well actuall its scss, but you get the idea) to make it work
html,
body{
height: 100%
}
l-table{
background: orange;
display: table;
height: 100%;
width: 100%;
}
.l-table-cell{
display: table-cell;
vertical-align: middle;
border: 2px solid black;
}
.square{
background: red;
margin: auto;
#media (orientation:landscape) {
width: 70vh;
height: 70vh;
}
#media screen and (orientation:portrait) {
width: 70vw;
height: 70vw;
}
}
http://codepen.io/johannesjo/pen/rvFxJ
For those who need it, there is a polyfill.

EDIT: Since writing the below, I appealed on Twitter and got a response from Brian Johnson. He came up with a solution that isn't 100% perfect semantically, but it's pretty damn good and I'll certainly be using it. He asked that I share it in this discussion. LINK
I'm having the same issue right now and I was just typing out pretty much this exact question, so although I can't answer it, I wanted to share what I've found so far in case it helps anyone come up with the final solution.
To clarify, I need my content to fit into a square which fills 60% of the browser's width if portrait or 60% of the height if landscape.
However, this square must never exceed the width or height of the viewport.
Using the technique found here I've managed to create the fluid square, but it still exceeds the viewport when landscape.
width: 60%;
height:0;
padding-bottom: 60%;
Link to Codepen example
I have tried flipping that technique on it's side for landscape but that doesn't work. (You can see that code in the above example, noted out.)
I can't use a simple max-height property because the height is being worked out by the padding-bottom property.
I've thought about adding an extra div as someone else has suggested (C-Link's post is really interesting) but I can't work out how I'd get it to do what we want it do here.

html
<div id="outer">
<div id="inner">YOUR CONTENTS HERE
</div>
</div>
css
html, body{
height: 100%;
}
#outer{
max-height: 100%;
max-width: 100%;
position: relative;
height: 100%;
}
#inner{
position: relative;
top: 50%;
margin-top: -50% auto auto auto;
background: red;
text-align: center;
color: yellow;
}
See this fiddle.

How about if you take the earlier concept a step further with a similar div as a container. The container has an added max-height & width. I tried this and the container does not throw a scrollbar at me. It is quite interesting in behavior I must say myself. Does this work for you?
<div id="container">
<div id="centered">A DIV</div>
</div>
#container {
top:0;
bottom:0;
right:0;
left:0;
margin:auto;
position:absolute;
width:200px;
height:200px;
max-width:100%;
max-height:100%;
background:#00f;
padding:0;
}
#centered {
background: green;
bottom: 0;
height: 80px;
left: 0;
margin: auto;
position: absolute;
top: 0;
right: 0;
width: 80px;
}
updated fiddle:
http://jsfiddle.net/djwave28/mBBJM/96/

Related

Scale square div according to height keeping ratio [duplicate]

This question already has answers here:
Maintain div aspect ratio according to height
(6 answers)
Closed 6 years ago.
I need to create a square with 100% height and width scaling according to the height, and so that it always keeps its aspect ratio.
Example illustration:
The popular example of a square div scaling is according to width (https://spin.atomicobject.com/2015/07/14/css-responsive-square/). I would like to solve this using CSS/flexbox, but I cannot find a proper solution.
(IE and legacy browser support is not important)
There has to be more than one element sharing the same style.
I've tried drawing it, but I dont know if this makes much sense. The individual squares need to fit the outer divs, but the three squares should not be the same size - rather fit their individual outer div.
I would like to give and idea of how I've tried doing this, but it is difficult to go into details because I've done a lot of things - none of them really working. I've tried absolute positioning, but that requires a width. I've tried calculating the width/height using jquery - this takes waaaay to long - as there are a lot of entries. I've tried using height:100% + width:auto, which renders nothing, I've tried the above solution that I've linked to (which is brilliant, yes sadly is based onthe width as a percent and not the height). etcetcetc!! :)
The solution in the question this has been linked to is not sufficient for my problem.
There is, unfortunately, no straight forward way to implement this in CSS alone. You could use viewport units as others have mentioned, but this is always relative to the entire viewport size. It turns out Javascript is the only way to make it more flexible:
document.addEventListener('DOMContentLoaded', function() {
var el = document.getElementById('square');
(window.onresize = function() {
el.style.width = el.clientHeight + 'px';
})();
});
html, body {
height: 100%;
margin: 0;
}
#container {
background: red;
height: 80%;
}
#square {
background: lime;
height: 100%;
margin: auto;
}
<div id="container">
<div id="square"></div>
</div>
Try this:
width: 100vh;
height: 100vh;
Demo:
body {
margin: 0;
}
.square {
width: 100vh;
height: 100vh;
background: grey;
margin: auto;
}
<div class="square"></div>
jsFiddle
.row {
display:table;
width:100%;
}
.row div {
display:table-cell;
vertical-align:top;
}
.col-1 ,.col-3{
background-color:red;}
.col-2 {
background-color:green;
}
<div class=row>
<div class="col-1">1</div>
<div class="col-2">2</div>
<div class="col-3">3</div>
</div>
You can work with Vh and calc
for this html
<div class="square"></div>
you can use this css
body {
background-color: #515151;
}
.square {
margin: 1vh auto;
background-color: #cacaca;
height: 98vh;
width: calc(99vh * 0.8);
}
you can see how works in this example

Is it possible to use CSS calc() in order to calculate an width/height ratio?

This is the code which I currently have (it does not work yet):
HTML:
<div class="chi_display_header" style="background-image:url('http://localhost/.../header-dummy-small.png');"></div>
CSS:
.chi_display_header {
background-size:contain;
width:100%;
min-height:100px;
height:calc(1vw * 270 / 1280px);
max-height:270px;
max-width:1280px;
margin:0 auto;
}
This is a centered responsive background image - the container should have a variable width / height and I do not want to use jQuery.
Known properties:
Ratio: 1280:270
Minimum height: 100px
Maximum height: 270px
Maximum width: 1280px
What I try to do is to calculate the container height of .chi_display_header magically with calc:
height = calc( CURRENT_SCREEN_WIDTH * 270 / 1280);
However my current approach
height:calc(1vw * 270 / 1280px);
does not work yet. Is there a CSS solution?
Solution (ty 4 comments):
.chi_display_header {
background-size:cover;
width:100%;
min-height:100px;
height:calc(100vw * 270.0 / 1280.0);
max-height:270px;
max-width:1280px;
margin:0 auto;
}
I applied Blackbam's solution to the situation where a div was placed in the body and the body had left and right padding of 15px. Subtracting the total left and right padding (30px) from the calculated height removed white-space that appeared above and below the div.
height:calc(100vw * aspect_ratio - 30px);
It's possible to do this without calc() as well. padding (even -top and -bottom) are relative to the element's width, so you can get the same effect thus:
.chi_display_header {
background-size: cover;
width: 100%;
min-width: 474px;
max-width: 1280px;
height: 0;
padding-bottom: 21.09375%;
}
You can also add elements inside with an inner <div> using the relative/absolute trick, though things will begin to go awry if the content exceeds the containing height:
.chi_display_header {
...
position: relative;
}
.chi_display_header .inner {
position: absolute;
top: 0; left: 0; right: 0;
padding: 15px;
}

Center content with twitter bootstrap

I am creating a login screen where there is a login box that I'd like to appear in the center of the screen (horizontally and vertically) no matter what resolution the user has.
I have looked around and can only find tutorials/articles that center content horizontally, which is half of what I want.
Any idea how I can achieve centralisation in both planes?
The best approach is using CSS and a Javascript callback for older IE versions.
CSS
.center {
width: 300px; // your login div width
height: 300px; // your login box height
position: absolute;
left: 50%;
top: 50%;
margin-left: -150px; // width/2
margin-top: -150px; // height/2
}
HTML
<div class="center">
Hey dude, I'm in the middle!
</div>
Live example
http://jsfiddle.net/86Asb/
Negative margins are exactly half the height and width, which pull the element back into perfect center. Only works with elements of a fixed height/width. This will work in all browsers except IE6,IE7 maybe.
The only way I know to vertically center an item is using javascript. Here is a simple example of how to do it using jquery and absolute positioning through CSS. Link to a jsfiddle and code to follow.
http://jsfiddle.net/AlienHoboken/XCPGe
Javascript:
$(document).ready(function() {
var width = $('#test').css('width');
var height = $('#test').css('height');
width = width.replace('px', '');
height = height.replace('px', '');
$('#test').css('left', ($(window).width()/2) - (width/2));
$('#test').css('top', ($(window).height()/2) - (height/2));
});
CSS:
#test {
position: absolute;
width: 50px;
height: 50px;
background: #000000;
}
I'm using the following solution (no fixed width of dialog), keeps it centered horizontally.
#test {
position: absolute;
max-width: 300px;
left: 1%;
right: 1%;
}
Any feedback / disadvantages appreciated!

Resize Images as viewport resizes without sides being cut off

I have a CSS problem. I have an image that is 1024x500 pixels. Now the problem is, whenever the browser window/viewport changes width below the width of the image(1024px), the image starts to get cut off. Now as you can see, I set the container width to 100% when the viewport size goes below 1024px, and it does resize proportionally, but the sides of my image get cut off more and more as the browser resizes(smaller).
Could anyone help me get my image to resize dynamically pixel for pixel (without losing any of the original picture - no cut offs)?
Check out my webpage and resize the browser window to see what I mean. Pay attention to the sides of the images getting cut away...
HTML: Note my Original image is 1024x500
<div class="ei-slider">
<ul class="ei-slider-large">
<li>
<img src="http://lamininbeauty.co.za/images/large/makeup.jpg" alt="Vertical Sunbed TanCan"/>
</li>
</ul>
</div>
CSS:
The normal CSS for large screens
.ei-slider{
position: relative;
width: 1024px;
height: 500px;
margin: 0 auto;
}
.ei-slider-large{
height: 100%;
width: 100%;
position:relative;
overflow: hidden;
}
.ei-slider-large li{
position: absolute;
top: 0px;
left: 0px;
overflow: hidden;
height: 100%;
width: 100%;
}
.ei-slider-large li img{
width: 100%;
}
For when the Browser window goes below the image width: 1024px:
#media screen and (max-width : 1023px){
.ei-slider{
width: 100%;
}
}
For smaller screens when my images are cut off: Note my Original image is 1024x500
#media screen and (max-width: 930px) and (min-width : 831px){
.ei-slider{
width: 100%;
}
.ei-slider-thumbs li a{
font-size: 11px;
}
.ei-slider-large li{
position: absolute;
top: 0px;
left: 0px;
overflow: visible;
height: 100%;
width: 100%;
}
.ei-slider-large li img{ /*HERE IS MY PROBLEM*/
width: 930px;
height: 454px;
}
}
Thank you!
you use:
max-width: 100%;
height: auto;
width: auto; /* for ie9 */
This will make whatever you assign the css to resize dynamically to fit its container based on the max-width: 100% statement. If you would like it differently, change the max width statement accordingly.
I have a simple solution for that. Just give the width parameter in terms of view-port percentage.
Syntax :
width: <Percentage>vw;
Example :
<img src="Resources/Head.png" alt="" style="width: 100vw; height: 85px">
Here, the height of the image is fixed but the width will be resized to 100% of the view-port, whatever its size may be.
Hope this helps :)
I had the same problem because I'm using the same jquery plugin (ie-slider). I found out that the image is passed additional (inline) styles from the Javascript code and in fact it is just shifted-left and not actually cut off. The code passes dynamic values to the tag which are got from the image itself at the time of re/load in a particular viewport width. The author uses this in the .js file.
var $img = $(this);
imgDim = _self._getImageDim( $img.attr('src')); //gets the dimensions from the image
He then gives the image a margin-left like so
$img.css({marginLeft: imgDim.left}); //assigns a new margin-left, overrides any value set for this property in the .css file because it's inline
When the viewport width gets smaller this is always a negative value. The work around is to set
$img.css({marginLeft: 0});
It worked fine for me after, with no arising issues from the change. Good luck.

CSS image scaling to fit within area not distort

Is there a way with CSS or otherwise of making an image fit within an area. Lets say I have multiple images of different sizes and I want them all to fit within a div of 150px by 100px. I don't want to scale the images though as some may be tall and others narrow I simply want them to fit within this area with the rest hidden.
I thought about using overflow:hidden but it appears to not be hidden in IE6.
Any ideas?
You should try using this:
img{
width: auto;
max-width: 150px;
height: auto;
max-height: 100px;
}
Edit: Looks like IE6 doesn't support max-width and max-height properties. However, you can implement the workaround given here: max-width, max-height for IE6
Excerpt (in case linked article stops working):
img {
max-height: 100px;
max-width: 100px;
width: expression(document.body.clientWidth > 150? “150px”: “auto”);
height: expression(document.body.clientHeight > 100? “100px”: “auto”);
}
When you say "fit within this area" with the rest hidden I feel like you want the image to not be scaled down at all and basically crop off any excess.
I might be interpreting you're question wrong, but try this and see if it produces the effect you're looking for.
.img-holder {
width: 150px;
height: 150px;
position: relative;
overflow: hidden;
}
.img-holder img {
position: absolute;
display: block;
top: 0;
left: 0;
}
<div class="img-holder">
<img src="http://img.playit.pk/vi/dH6NIe7wm4I/mqdefault.jpg" />
</div>
This won't work in IE6 (as required by the OP), but for completeness you can achieve the required effect on newer browsers using CSS3's background-size:cover and setting the image as a centered background image. Like so:
div {
width:150px;
height:100px;
background-size:cover;
background-position:center center;
background-repeat:no-repeat;
background-image:url('somepic.jpg');
}
I know this is an old one, but because I found it in search of answer for the same question, I guess it could be of use for someone else, too.
Since the answers were posted, CSS property object-fit was brought to us. It does exactly what was once requested in the question.
For reference: https://www.w3schools.com/css/css3_object-fit.asp
This worked for me:
img.perfect-fit {
width: auto;
height: auto;
min-width: 100%;
min-height: 100%;
}
It tries to do a "perfect fit" of the container, stretching itself to fit the bounds while maintaining image proportion. Haven't tested it with IE6.
JSFiddle: http://jsfiddle.net/4zudggou/
Hope I am not late to the party ;)
img {
width:inherit;
height:inherit;
object-fit: cover;
}
if however you want the full image to display, use the code below
img {
width:inherit;
height:inherit;
object-fit: contain;
}
this should do the trick.

Resources