Why is there no easy was to vertically center in css? - css

I was searching around for a way to vertically center a div in a container. I found a few different ways, but all of them seemed to be very "hacky".
My question is, why is there not just a css property, such as align-vertical that can simply be set to center to center the content? It seems like adding this to css would make so many things much easier.
I am assuming there must be a reason why something like this is not implemented, and I would like to hear if anyone has any idea why.

It's because how browsers traditionally work.
In a browser, by default, the content scrolls vertically. The viewport width is well defined (width of the device), but the viewport height can be one or two times the height of the device, or can even be infinite (as in infinite scrolling).
Traditionally blocks were meant to be horizontally oriented. You place a div and it's automatically occupying 100% of the width of the parent. But its height value is contrained to its content.
If you do
.mydiv {
background: red;
width: 100%;
height: 100%
}
Nothing changes, since divs have already 100% of width, and it can't calculate the height, since it doesn't know how far the viewport will go. You need to add:
html, body {
height: 100%;
}
to tell the browser to use the device height as the 100% value.
That's why horizontal center is easy: you know what the boundaries are, and how to center the element. But vertical center is more complicated, that's why (before flexbox), you need to resort to absolute positioning or hacks.
Flexbox allows you to render content horizontally or vertically, so it's prepared to handle centering along two axes.
If you want to read more about this, I suggest the spec:
Visual formatting model
Visual formatting model details

#outerDiv{
display:flex;
width:100%;
height:200px;
background:#ccc;
align-items:center;
}
#innerDiv {
background:#aaa;
width:80%;
margin:0 auto;
}
<div id="outerDiv"><div id="innerDiv">Hello</h1></div>
Run the script and the div remain in the center.
You can mix and match the combination like this.
Earlier you need to play with the height of the parent container and self height.
But with flex it becomes easy.

If I'm trying to center an element I do the following -
*parent-item {
margin: 0 auto;
width: 100%;
display: block;
It's important to define the width of the element you are centering.

Related

How can I center an <img> inside a div and have it scale with the div's height?

I'm using centered imgs to act as backgrounds for some tiles. I'm trying to have these images scale with their parent div's height and if they are wider then their parent's for them to hide the overflow.
Example:
* I've got it working now. Answers are below, I'm updating this code to display all I needed to use to get it to work *
HTML
<div class="container">
<img class="derp" src="http://gridiculo.us/images/kitty02.jpg">
</div>
CSS:
.container {
height:250px;
width:50%;
}
.derp{
object-fit: cover;
height: 100%;
width: 100%;
}
Here's a near-example: http://codepen.io/chriscoyier/pen/myPMGB
The difference would be that I'm using s and not background-image, and that instead of the img filling the div completely it would fit to the height and hide the width overflow.
I'm trying to avoid using background-image since I'm using a lot of these tiles and making CSS rules for every one isn't going to work.
In order to scale it with the div's height, I'd change the height from px to % - this way, the larger's the div, the larger's the picture. In order to certain the image, i'd use margin in the image css. That'd look like so:
.derp{
height:80%;
width:80%;
margin:10%;
}
.container {
height:250px;
width:50%; /* needed */
/* inner img is centered horizontally */
vertical-align:top;
text-align:center;
overflow-x:hidden;
}
<div class="container" style="background-color:gray"> <!-- The background is there so you could see the image relative to the div -->
<img class="derp" src="http://gridiculo.us/images/kitty02.jpg">
</div>
The best way to keep the aspect ratio of the image is to set the width to auto (and it's the default behavior so you don't need to set explicitly). And with a simple overflow:hidden it works almost as you want it.
The hard part is centering horizontally. You can try this answer :css to center a image horizontally.
However if all your images aren't the same size, you will need to make one rule per image. And in this case putting the image as background-img would be better for semantic and accessibility (because your image doesn't have a sense in the page, it doesn't convey any information, it's decoration). An <img> would be read by a screen reader (the alt attribute), and in your case it wouldn't help a blind people.
Depending on how many browsers you need to support, I'd suggest you use object-fit! Support for it is okay if you can ignore IE, but in case your project qualifies, I see no problem with using it today. Also, there is always a polyfill.
You can find a nice summary on CSS-Tricks.com about the property. It basically works similarly to background-size, but for <img> tags. In your case, object-fit: cover; does the trick.
I made a little demo on CodePen that shows you how it works.
img {
height: 100%;
object-fit: fill;
width: 100%;
}

Expanding the parent container with 100% height to account for floated content

I'm struggling with a client project. All of my divs have no absolute positioning, height:100% for html, body, and container divs, and yet the static-content stops short of its contents (at 910px).
I can change the overflow property to auto, and the background will continue down to the end of the content, but it adds a scroll bar, and the bottom border of the static-content div stays in the same place (at 910px).
UPDATE: Development link was no longer valid, so I removed it. Suffice to say that Animuson's thorough explanation is the valuable part of this thread, and solved the problem of containers not expanding to match their content. – Ty
You used the wrong overflow-y property for clearing, and you should set a min-height instead of a regular height. Try this:
#static-content {
background-color: #FFFFFF;
margin: 0 auto;
min-height: 100%; /* Set to minimum height so overflow doesn't get hidden */
overflow-y: hidden; /* HIDE overflow; I know, it doesn't make much sense */
position: relative;
width: 960px;
}
Floating Content by Itself
Given this green box which has a padding of 20px (for visibility), notice how a single red box floated to the left will expand past the boundary of its parent box. This is because floating content doesn't actually take up any "space" in the visual area. All other elements will expand underneath it, and only text will wrap around it.
Clearing Floated Content in the Parent
In order to counter this and make the green box completely encompass the area of its child red box, we can add overflow: hidden to its styles. This will expand the box down far enough.
Expanding the Parent to 100% Height
You might think that just adding height: 100% is the simplest way to make it expand to where it needs to be.However, the height property specifies an absolute height. Since the content which is floated does not actually take up any vertical space, our overflow: hidden property will cut off all the content that goes past the parent's height.
Using a Minimum Height Instead
Since we want it to expand to at least a 100% height, we can use the min-height property to force it there and still maintain the "automatic" height needed to make the parent green box fully encompass the child red box, letting it push past the 100% only when it needs too.
How You Were Set Up
All elements, by default, are set to overflow: visible so that property didn't really change anything. The only difference you had between this and the first example I provided was that you had a height: 100% set on the element. So the parent was expanding to 100% height but still not encompassing the full height of its child red box.
If you have to use overflow:visible for some reason, there's other way to force container to stretch to contain all floated content. You have to put element with clear:both as a last container's elements. If you ignore ancient IEs (<8) you can do it with very simple css (vide https://css-tricks.com/snippets/css/clear-fix/):
.your-container:after {
content: "";
display: table;
clear: both;
}
If height: 100% doesn't work well for you, you can try this calc function from CSS3:
/* Firefox */
height: -moz-calc(100%);
/* WebKit */
height: -webkit-calc(100%);
/* Standard */
height: calc(100%);
You can try this either with height, or with min-height, as already said. You can with this calc functions also other calculations like:
height: -moz-calc(100% - 50px);
And this is sometimes very useful, as you might guess.
height:100% is the height of the content that flows with your container at hand and is not taking into account your floated content, so that is why the height of your container is stopping short. Remove it and clear your container properly to clear your floated elements within and it will work:
#static-content:before, #static-content:aftr {
display:table;
content:"";
}
#static-content:after {
clear:both;
}
#static-content {
zoom:1; /*ie fix*/
}
You have a float in static-maincontent, which removes it from the regular flow of the content of the document, and hence static-content doesn't care about its height any more, and so won't expand to cover it.
Additionally, remove height:100% for static-content.
READ FOR ANSWER!!!-- Okay so I had the same problem, All that was needed was to remove the "Positioning" Style. Should work perfectly fine.

css resize div proportionally, similar to image resize

is it possible to have a div (or other element) resize its height in relation to its width (or the other way around) using CSS? basically, to get it to behave the way an image with a percentage width resizes proportionally as the browser window is resized?
If you want to set a width or height relative to a .parent element and you know the aspect ratio that needs to be maintained, you can do something like this:
.parent{
width: 150px;
}
.child{
width: 100%;
padding-top: 50%; /* outer height will be 75px (150px*0.5) */
}
Note that you are relying on having a height (or width) of 0 and defining it based on the padding only. So, if you want to add any content you will probably need to wrap it within an absolutely positioned div within .child. See this fiddle for an example
Look at this related question. In short: No, it's not possible using only CSS

How to keep text resize from affecting div height?

I'm working on a website where disabled access is one of the primary requirements. To do this, I've implemented a Javascript font size increase/decrease function that works great.
However, the div element where the resized text resides changes height based on the text size while everything else stays the same. Width doesn't change, but the height property set to 100% makes no difference. What changes to the CSS are necessary to keep the height fixed? so the footer content as well as the content element background stay the same?
This is the container element where all other divs are nested inside:
#container{
width:1000px;
height:100%;
background-color:#FEFFF1;
margin: 0 auto;
margin-top:5px;
text-align: left;
font-size:1.4em;
border: 1px dotted black;
overflow:scroll;
}
This is the content element, where the page-unique content goes:
#content{
float:left;
margin-top: 223px;
margin-left:250px;
height:100%;
width: 70%;
overflow:auto;
padding-bottom:120px;
position:relative;
}
EDIT changed container overflow value to scroll, where it should have been originally.
If you don't allow the containers that hold the text to expand with the text, then what's the point of letting people resize the text?
Note that text-size is not an issue for 'disabled' people. It's an issue for everyone. On the plus side, we're finally at the point where browsers are adding this as a much more usable and findable feature than in the past. As such, writing your own JS based text-resizing widgets isn't as big of a deal as it once was.
To answer your specific question, height, in CSS, refers to the height of the page (at the outer level) or whatever container it is nested within. It will exceed said height if need be if the contents overflows, unless you provide an overflow value of SCROLL or HIDDEN, which, again, defeats the purpose of the font resizing. Your best bet is to make sure your page design/layout can handle variable font sizes.
Just specify a fixed height instead of a percentage. As in

Seeking CSS Browser compatibility information for setting width using left and right

Here's a question that's been haunting me for a year now. The root question is how do I set the size of an element relative to its parent so that it is inset by N pixels from every edge? Setting the width would be nice, but you don't know the width of the parent, and you want the elements to resize with the window. (You don't want to use percents because you need a specific number of pixels.)
Edit
I also need to prevent the content (or lack of content) from stretching or shrinking both elements. First answer I got was to use padding on the parent, which would work great. I want the parent to be exactly 25% wide, and exactly the same height as the browser client area, without the child being able to push it and get a scroll bar.
/Edit
I tried solving this problem using {top:Npx;left:Npx;bottom:Npx;right:Npx;} but it only works in certain browsers.
I could potentially write some javascript with jquery to fix all elements with every page resize, but I'm not real happy with that solution. (What if I want the top offset by 10px but the bottom only 5px? It gets complicated.)
What I'd like to know is either how to solve this in a cross-browser way, or some list of browsers which allow the easy CSS solution. Maybe someone out there has a trick that makes this easy.
The The CSS Box model might provide insight for you, but my guess is that you're not going to achieve pixel-perfect layout with CSS alone.
If I understand correctly, you want the parent to be 25% wide and exactly the height of the browser display area. Then you want the child to be 25% - 2n pixels wide and 100%-2n pixels in height with n pixels surrounding the child. No current CSS specification includes support these types of calculations (although IE5, IE6, and IE7 have non-standard support for CSS expressions and IE8 is dropping support for CSS expressions in IE8-standards mode).
You can force the parent to 100% of the browser area and 25% wide, but you cannot stretch the child's height to pixel perfection with this...
<style type="text/css">
html { height: 100%; }
body { font: normal 11px verdana; height: 100%; }
#one { background-color:gray; float:left; height:100%; padding:5px; width:25%; }
#two { height: 100%; background-color:pink;}
</style>
</head>
<body>
<div id="one">
<div id="two">
<p>content ... content ... content</p>
</div>
</div>
...but a horizontal scrollbar will appear. Also, if the content is squeezed, the parent background will not extend past 100%. This is perhaps the padding example you presented in the question itself.
You can achieve the illusion that you're seeking through images and additional divs, but CSS alone, I don't believe, can achieve pixel perfection with that height requirement in place.
If you are only concerned with horizontal spacing, then you can make all child block elements within a parent block element "inset" by a certain amount by giving the parent element padding. You can make a single child block element within a parent block element "inset" by giving the element margins. If you use the latter approach, you may need to set a border or slight padding on the parent element to prevent margin collapsing.
If you are concerned with vertical spacing as well, then you need to use positioning. The parent element needs to be positioned; if you don't want to move it anywhere, then use position: relative and don't bother setting top or left; it will remain where it is. Then you use absolute positioning on the child element, and set top, right, bottom and left relative to the edges of the parent element.
For example:
#outer {
width: 10em;
height: 10em;
background: red;
position: relative;
}
#inner {
background: white;
position: absolute;
top: 1em;
left: 1em;
right: 1em;
bottom: 1em;
}
If you want to avoid content from expanding the width of an element, then you should use the overflow property, for example, overflow: auto.
Simply apply some padding to the parent element, and no width on the child element. Assuming they're both display:block, that should work fine.
Or go the other way around: set the margin of the child-element.
Floatutorial is a great resource for stuff like this.
Try this:
.parent {padding:Npx; display:block;}
.child {width:100%; display:block;}
It should have an Npx space on all sides, stretching to fill the parent element.
EDIT:
Of course, on the parent, you could also use
{padding-top:Mpx; padding-bottom:Npx; padding-right:Xpx; padding-left:Ypx;}

Resources