Most heavily supported methods of vertical alignment? - html

Until recently I have been using Flexbox to vertically align elements like so:
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-ms-flex-align: center;
-webkit-align-items: center;
-webkit-box-align: center;
align-items: center;
However I have begun working on more and more projects that need to support older browsers which do not support Flexbox e.g. Internet Explorer 8. I would like to begin supporting a much wider range of browsers and devices.
My question is; what are some of the most heavily supported methods of vertical alignment using just HTML and CSS?
In most cases the elements I'm centring will not have fixed heights or widths, generally the width will be a percentage value and the height will be determined by dynamic content.
Thanks in advance.

If you don't have the luxury of knowing the exact size of the box you want to align to the middle, then I usually go with the display:table-* css setup.
Putting the content box into a div with display:table-cell wrapped in a display:table element does the trick.
This solution's browser compatibility is pretty good.
Html
<div class="popup">
<div class="popup-table">
<div class="popup-table-cell">
<div class="popup-body">Hello there!</div>
</div>
</div>
</div>
Css
.popup{position:fixed;top:0;left:0;bottom:0;right:0;}
.popup-table{display:table;width:100%;height:100%;}
.popup-table-cell{display:table-cell;vertical-align:middle;text-align:center;}
.popup-body{display:inline-block;border:1px solid black;padding:3em;}
Uploaded a code example here: http://codepen.io/anon/pen/NdGpje
** Please note, that the .popup class is a wrapper only, you don't have to use it - it's just to have a simple usecase for middle positioning, and a wrapper element for .popup-table.

Here is a very simple example from CSS Tricks. You can set the elements top margin to 50% and then raise it up by half its height. Here is the code:
body {
background: #f06d06;
font-size: 80%;
}
#div1 {
background: white;
height: 300px;
margin: 20px;
width: 300px;
position: relative;
resize: vertical;
overflow: auto;
}
#div1 div {
position: absolute;
top: 50%;
left: 20px;
right: 20px;
background: black;
color: white;
padding: 20px;
transform: translateY(-50%);
resize: vertical;
overflow: auto;
}
<body>
<div id="div1">
<div>
I'm a block-level element with an unknown height, centered vertically within my parent.
</div>
</main>
</body>

The technique I personally use to vertically align content in a div is with display: table; display: table-cell; and vertical-align:middle; like so:
HTML:
<div class="block">
<div class="block__module">
<h1>Title</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec commodo pellentesque est quis mollis. Nulla suscipit risus a ornare viverra. Suspendisse potenti. Phasellus tempor imperdiet ullamcorper. Nam accumsan volutpat tincidunt. Cras eu mauris posuere, imperdiet elit ac, rutrum ligula. Maecenas ullamcorper sit amet nisi vitae consectetur. Sed ultrices lorem a fermentum lacinia.
</p>
</div>
</div>
CSS:
.block {
display:table;
height: 500px;
width:100%;
}
.block__module {
display:table-cell;
vertical-align:middle;
}
Here is a fiddle link with my code.
I understand that your content may be dynamic, I am not sure if changing the height of the div to 100% will help and achieve the same result but this way of vertical alignment works in at least IE8 plus. I always declare a height but I understand that this is not something that we can always do.
I found a similar question to this one on SO that may be of help, please see here.
I also came across this handy code generator that may help, please see here. It gives you the choice of filling in some values and generates the best option for vertical alignment.

Related

How to "left-align" a table in the "center" of the page?

This may be a weird one:
I have a page where I don't control the HTML, but I can inject some additional CSS.
I have some tables which I need to align on the page. The problem is that all the other elements are aligned center on the page, but they all have fixed width. For aesthetic reasons I don't want all the tables to be of the same width, I want them to be of variable width depending on the contents.
Notice in the below code how the main container is full width on the page and the other content does not have any other wrapper elements around them. Because of this, all individual items are centered on the page using css. And also because the main container has other full width children (that I have not shown here), I cannot make the container be of reduced width and center it.
*, *:before, *:after {
box-sizing: border-box;
}
.content {
width: 100%;
background-color: #ddd;
}
.content p,
.content span,
.content table {
display: block;
max-width: 300px;
margin-left: auto;
margin-right: auto;
background: #999;
}
<div class=content>
<span>Some content header </span>
<p>Some content which can be long.. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse ac blandit nisi. Curabitur fermentum dui tortor, sed rutrum velit facilisis non. Aliquam erat volutpat. Phasellus egestas erat sapien, ac scelerisque erat rhoncus id. Nullam aliquam libero et aliquam bibendum. Curabitur porttitor lorem in libero molestie, vitae ornare lacus fermentum. Curabitur condimentum tellus fermentum, feugiat nunc dictum, commodo est.</p>
<table class=table1>
<tr>
<td>Test Table 1</td>
</tr>
</table>
<br/>
<table class=table2>
<tr>
<td>Test table 2 which need to have more width than the first one</td>
</tr>
</table>
</div>
What I finally want looks something like this image:
Notice that:
The tables are left aligned with the rest of the items in the page.
The tables are of different width.
Obviously I don't want to hardcode the widths or the left margin for the tables.
Any idea if I can achieve this using just CSS?
Add the following CSS to an outer wrapper on your table:
.wrapper {
display: block;
margin: auto;
max-width: 80%;
}
Add this CSS to your table:
table th, table td {
text-align: left;
}
The CSS above will both center your table to 80% of the screen width as well as left align all text within it.
Update
If you cannot center the wrapper element, use flexbox on the wrapper element instead to center all of the children.
.wrapper {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
The CSS above makes it so that any element that is a direct child of the wrapper will be centered, so all elements will be equally centered, including your table. If you want them equally spaced between each other, change justify-content: center; to justify-content: space-between;.

how to make a div scrollable inside an iframe which is wrapped in a div

I have a div wrapper which contains an iframe, and inside the iframe I have a two divs, one needs to be a fixed header and the other one should be a scrollable content. But the problem is that the whole iframe is scrollable also with the header div which should be fixed. I already tried setting the #header div to position: fixed or absolute but that is not good solution because it shows the scrollbar even on the header div. Can I have scrollbar only for the #content div?
Here is my code
file1 html:
<div id="iframeWrapper">
<iframe src="http://jsbin.com/lixegeriru" scrollable="no"></iframe>
</div>
file1 css:
#iframeWrapper {
width: 250px;
max-height: 500px;
}
iframe {
overflow: hidden;
border: 2px solid black;
width: 100%;
}
file2 html:
<div>
<div id="header">
this is a fixed header
</div>
<div id="content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed facilisis aliquet felis non tempor. Nam sit amet ultrices lectus. Suspendisse nibh justo, hendrerit in pulvinar ac, interdum ac orci. Quisque mollis augue nec posuere ullamcorper. Phasellus accumsan semper urna, non posuere ligula consectetur vel.
</div>
</div>
file2 css:
#header {
width: 100%;
height: 42px;
background-color: #ff4045;
color: white;
padding: 5px;
}
#content {
height: 2000px;
overflow: auto;
}
live demo here http://output.jsbin.com/wepoxetovi
EDIT: this question was marked as duplicate of HTML iframe - disable scroll
I disagree, my problem is not to hide the scrollbar, but use it only on the #content div, therefore the answer on the other questions are not related nor solving my problem.
EDIT 2: this question was again marked as a duplicate of Making a div vertically scrollable using CSS
Again, I disagree on this, because the provided answer does not solve my problem for this case.
Thanks to #CBroe I could solve this issue.
My iframe needed height to be defined.
iframe {
overflow: hidden;
border: 2px solid black;
width: 100%;
height: 500px;
}
Here is a working example
http://jsbin.com/roluvayoke/1

Two p tag in same line

I have two p tags
<p style="margin: 0; display: inline;">content1</p>
<p style="margin: 0; display: inline;" align="right">content2</p>
The Output is content1content2. My expectation is like this:
content1 content2
Can anyone help. I want one "content1" in the left p and "content2" in the right 'p'.
You can use CSS flexbox for this. Below is the minimal CSS for the requested layout:
<div style="display: flex; justify-content: space-between;">
<p style="background-color: papayawhip;">Lorem ipsum dolor sit amet.</p>
<p style="background-color: palegoldenrod;">Donec eget luctus lacus.</p>
</div>
For longer content, you can use fixed-width columns:
<div style="display: flex; justify-content: space-between;">
<p style="flex-basis: 49.5%; background-color: papayawhip;">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec eget luctus lacus. Cras consectetur elementum mi sed consequat.</p>
<p style="flex-basis: 49.5%; background-color: palegoldenrod;">Pellentesque aliquet condimentum augue in mattis. Praesent sagittis nisl magna, a volutpat arcu imperdiet vel. Quisque et orci sed ligula cursus luctus.</p>
<!-- 49.5% + 49.5% = 99%, remaining 1% is distributed according to justify-content -->
</div>
You could do it with floats:
<p style="margin:0;display:inline;float:left">content1</p>
<p style="margin:0;display:inline:float:right" >content2</p>
The idea of the tag <p></p> is to display a paragraph. So HTML offers you the <div></div> which is a container conecpt. So you should use Salman A's Solution, because there aren't just different tags in html for no reason. Actually you can style a paragraph with css so it is getting displayed the same as a div container, but it is not meant to be like that.
I don't want to say to you, what you have to do. I just wanna help you using the "correct" tags for the things they were made for.
What you really want is something that doesn't assume sufficent width to fit both paragraphs into one line:
* { box-sizing: border-box; }
.two { width: 30em; max-width: 100%; }
.two p { display: inline-block; max-width: 50%; }
.two p:nth-child(1) { float:left; }
.two p:nth-child(2) { float:right; }
<div class="two">
<p>This is the first paragraph of two.</p>
<p>This is the second paragraph of two.</p>
</div>
Here's another quick turnaround to achieve this:
p{
text-align: center;
}
.item p{
display: inline-block;
}
.leftContent{
text-align: left;
width: 50%;
}
.rightContent{
text-align: right;
width: 50%
}
<br>
<!--Use both P tags in the same line without space -->
<article class="item">
<p class="leftContent">Content1</p><p class="rightContent">Content2</p>
</article>
float:left, float:right.... or
width:49.9%;
display:inline;
text-align:left;
text-align:right;

When a child element overflows horizontally, why is the right padding of the parent ignored?

Given this simple structure:
<div id="parent">
<div id="child">Lorem ipsum</div>
</div>
with this CSS:
#parent {
width: 200px;
height: 200px;
padding: 20px;
overflow-x: scroll;
}
#child {
width: 500px;
}
Live demo: http://jsfiddle.net/523me/5/
Notice that the parent has a 20px padding and that the child overflows horizontally (because it is wider). If you scroll the parent all the way to the right, you'll see that the child touches the right edge of the parent.
So, the parent should have a right padding, but it is ignored. It seems that when the child has a fixed width, the right padding of the parent does not apply. (Is this specified by a standard? I would love to know. Please let me know if you find anything!)
Is there a way to force the right padding to be applied in this scenario without having to remove any of the elements from the flow (by floating or positioning)?
Screenshot 1 - The right padding is ignored. This is how all current browsers behave.
Screenshot 2 - The right padding applies. This is what I'm trying to accomplish. (Btw, the screenshot is from IE7, which is the only browser which does not ignore the right padding.)
You're suffering from this problem.
I would solve it by giving a margin to the child (and not a padding to the parent):
body {
padding: 2em;
}
#parent {
width: 200px;
height: 200px;
overflow-x: scroll;
background: gray;
}
#child {
width: 500px;
background: yellow;
margin: 20px;
display: inline-block;
}
<div id="parent">
<div id="child">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras et turpis eu lorem consectetur blandit sed vel ligula. In lorem ligula, lacinia sed aliquet sed, congue quis tortor. In sed magna eros, eget blandit arcu. Nulla sit amet volutpat ipsum. Duis
quis nisl massa. Sed ipsum magna, tempus non malesuada in, gravida et sapien. Fusce a odio nulla, quis ultrices mauris. Maecenas in tellus id massa fringilla molestie.</div>
</div>
Dunno but adding:
#child{
display: inline-block;
}
Seems to fix it: http://jsfiddle.net/523me/6/
I've only tested in latest Chrome, may not be cross-browser
You might change the padding to a border.
padding: 20px;
to
border: 20px solid gray;
No, the padding is not ignored, but it's still inside the parent.
See updated jsFiddle, where you can see that the padding hasn't moved from its original position.
Edit: Hm, there are some anomalies. If you give the inner div a right margin, that gets ignored too. Hm. Upvoting your question.
Apply padding-right to overflowing element itself, and move background to its direct child element.
<div id="parent">
<div id="child"><div>Lorem ipsum...</div></div>
</div>
<style>
#parent {padding-right: 0; }
#child {padding-right: 20px; }
#child > DIV {background: yellow; }
</style>
http://jsfiddle.net/523me/9/

How to position a DIV to fill all available space between a header DIV and a footer DIV?

Let's say I have a parent DIV. Inside, there are three child DIVs: header, content and footer. Header is attached to the top of the parent and fills it horizontally. Footer is attached to the bottom of the parent and fills it horizontally too. Content is supposed to fill all the space between header and footer.
The parent has to have a fixed width and height. The content DIV has to fill all available space between header and footer. When the content size of the content DIV exceeds the space between header and footer, the content DIV should display scrollbars and allow appropriate scrolling so that the footer contents should never be obscured nor the footer obscure content.
Now comes the hard part: you don't know the height of the header nor footer beforehand (eg. header and footer are filled dynamically). How can content be positioned without using JavaScript?
Example:
<div style="position : relative; width : 200px; height : 200px; background-color : #e0e0ff; overflow : hidden;">
<div style="background-color: #80ff80; position : absolute; left : 0; right : 0; top : 0;">
header
</div>
<div style="background-color: #8080ff; overflow : auto; position : absolute;">
content (how to position it?)
</div>
<div style="background-color: #ff8080; position : absolute; bottom : 0px; left :0; right : 0;">
footer
</div>
</div>
To clarify this event further - the target layout that I'm trying to achieve will be used in a business web application. The parent DIV will have a fixed, but unknown size (for instance, it will be exactly the size of the browser viewport, sizing itself along with sizing the browser window by the user). Let's call the parent DIV a "screen".
The header will contain a set of filtering controls (like textboxes, drop down lists and a "filter" button) that should wrap to the next line if there is insufficient horizontal space (so its height can change any time to accomodate line breaking). The header should always be visible and attached to the top of the "screen".
The footer will contain a set of buttons, like on a dialog window. These too can wrap to next line if there is not enough space horizontally. The footer must be attached to the bottom of the "screen" to be accessible and visible at all times.
The content will contain "screen" contents, like dialog fields etc. If there are too few fields, the rest of the content will be "blank" (in this case the footer should not begin right after the content, but still be attached to the bottom of the "screen" which is fixed size). If there are too many fields, the content DIV will provide scrollbar(s) to access the hidden controls (in this case the content DIV must not extend itself below the footer, as the scrollbar would be partially hidden).
I hope this clarifies the question a little bit further, as I have too low rep to enter comments to your repsonses.
I'm going to get downmodded for this, but this sounds like a job for a table.
What you're trying to do is to set the total height of three contiguous divs as a unit, and a 1x3 table with height 100% is actually a cleaner solution.
Pure CSS Solution 1 - Flexbox:
You can create a column of divs that behave in this way by using the CSS3 display: flex; property (see W3 Specs)
Using a wrapper, you can align everything in a column with the flex-direction: column; declaration and then fill the vertical space with justify content: space-between; and height: 100vh;. Then all you need to do is make your content element expand with flex: 1 0 0; and give it a scrollbar with overflow-y: auto;.
Note on browser support - While flexbox is supported by most modern browsers, there are still a few limitations (see: http://caniuse.com/#feat=flexbox). I would recommend using the -webkit- and -ms- prefixes.
Working example: See the following snippet and this jsfiddle.
body {
display: -webkit-flex; /* Safari 6.1+ */
display: -ms-flex; /* IE 10 */
display: flex;
-webkit-flex-direction: column; /* Safari 6.1+ */
-ms-flex-direction: column; /* IE 10 */
flex-direction: column;
-webkit-justify-content: space-between; /* Safari 6.1+ */
-ms-justify-content: space-between; /* IE 10 */
justify-content: space-between; /* Header top, footer bottom */
height: 100vh; /* Fill viewport height */
}
main {
-webkit-flex: 1 0 0; /* Safari 6.1+ */
-ms-flex: 1 0 0; /* IE 10 */
flex: 1 0 0; /* Grow to fill space */
overflow-y: auto; /* Add scrollbar */
height: 100%; /* Needed to fill space in IE */
}
header, footer {
-webkit-flex: 0 0 auto; /* Safari 6.1+ */
-ms-flex: 0 0 auto; /* IE 10 */
flex: 0 0 auto;
}
/* Make it look a little nicer */
body {
margin: 0;
background-color: #8080ff;
}
header {
background-color: #80ff80;
}
footer {
background-color: #ff8080;
}
p {
margin: 1.25rem;
}
<body>
<header>
<p>header</p>
</header>
<main>
<article>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pellentesque lobortis augue, in porta arcu dapibus dapibus. Suspendisse vulputate tempus venenatis. Pellentesque ac euismod urna. Donec dui odio, ullamcorper in posuere eu, laoreet sed nisl. Sed vitae vestibulum leo. Maecenas mattis lacus eget nisl malesuada, quis semper urna ornare. Praesent id mauris nec neque aliquet dignissim.</p>
<p>Morbi varius dolor at lorem aliquet lacinia. Aliquam id lacinia quam. Sed vel libero felis. Etiam et pellentesque sem. Aenean bibendum, ante quis luctus tincidunt, elit mauris volutpat nisi, et tempus lectus sapien in mauris. Aliquam condimentum nisl ut elit accumsan hendrerit. Morbi mollis turpis est, id tincidunt ipsum rhoncus eget. Fusce in feugiat lacus. Quisque vel massa magna. Mauris varius congue nisl, vitae pellentesque diam ultricies at. Sed ac nibh ac diam tristique venenatis non nec nisl. Vivamus enim eros, pretium at iaculis nec, pharetra non sem. Aenean ac imperdiet odio.</p>
<p>Morbi varius dolor at lorem aliquet lacinia. Aliquam id lacinia quam. Sed vel libero felis. Etiam et pellentesque sem. Aenean bibendum, ante quis luctus tincidunt, elit mauris volutpat nisi, et tempus lectus sapien in mauris. Aliquam condimentum nisl ut elit accumsan hendrerit. Morbi mollis turpis est, id tincidunt ipsum rhoncus eget. Fusce in feugiat lacus. Quisque vel massa magna. Mauris varius congue nisl, vitae pellentesque diam ultricies at. Sed ac nibh ac diam tristique venenatis non nec nisl. Vivamus enim eros, pretium at iaculis nec, pharetra non sem. Aenean ac imperdiet odio.</p>
</article>
</main>
<footer>
<p>footer</p>
</footer>
</body>
For more information on how to use flexbox see these guides:
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Flexible_boxes
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
Pure CSS Solution 2 - Display Table [Old solution]:
This can also be done by using the CSS display: table; property (see W3 Specs).
The HTML:
<div id="screen">
<div id="header"></div>
<div id="content">
<div id="content_frame">
<div id="content_wrap"></div>
</div>
</div>
<div id="footer"></div>
</div>
The CSS:
html, body, #screen, #content, #content_frame {
height: 100%; /* Make #screen viewport height and #content fill space */
}
#screen {
display: table;
}
#header, #content, #footer {
display: table-row;
}
#content_frame {
overflow-y: auto; /* Add scrollbar */
position: relative;
}
#content_wrap {
position: absolute; /* Fix problem with overflow in FF */
}
The overflow property is unreliable on css table elements and their children, so I had to nest the content. In this case I was forced to nest twice and use position: absolute; in order to make it work in Firefox. Maybe someone else can come up with a more elegant solution to avoid this 'divitis'.
Here is a functioning jsfiddle.
Warning: This does not appear to work in Opera 12! The content div takes up 100% of the parent's height which causes the rows to overflow the table (as they did in firefox).
If you can get away with not having the main content scrollable, you might be better using the footerStickAlt method to make sure your footer stays at the bottom of the screen or the bottom of the content (if the content extends beyond the bottom of the screen).
Does the parent need to stay at a fixed height?
<div style="position : relative; width : 200px; background-color : #e0e0ff; overflow : hidden;">
<div style="float: left; clear: left; background-color: #80ff80;">
header
</div>
<div style="float: left; clear: left; background-color: #8080ff; overflow : auto; ">
content (how to position it?)
<BR />taller
<BR />taller
<BR />taller
<BR />taller
<BR />taller
<BR />taller
<BR />taller
<BR />taller
</div>
<div style="float: left; clear: left; background-color: #ff8080;">
footer
<BR />taller
</div>
if the height of the parent is fixed, this is the closest I'd know how to get to it offhand -- still not exactly right if those color blocks (as opposed to just text) are truly important and weren't just for illustrating the boundaries of the DIVs:
<div style="position : relative; width : 200px; height : 200px; background-color : #e0e0ff; overflow : hidden;">
<div style="float: left; clear: left; background-color: #80ff80; ">
header <BR .> taller
</div>
<div style="float: left; clear: left; background-color: #8080ff; overflow : auto; ">
content (how to position it?)<BR /> and another line
</div>
<div style="background-color: #ff8080; position : absolute; bottom : 0px; left :0; right : 0;">
footer <BR /> taller
</div>
Do you need to have the center div change size? If you're just trying to make sure that it appears that its background (#8080ff) appears between the header and the footer, why not just have the containing div's background be #8080ff. The header and footer background would override that, and the rest of the div's background would be correct.
Absolute positioning is messing you up. Try something like this:
HTML:
<div id="wrapper">
<div id="header">
header
</div>
<div id="content">
content
</div>
<div id="footer">
footer
</div>
</div>
CSS:
#wrapper {
width: 200px;
height: 200px;
overflow: visible;
background: #e0e0ff;
}
#header {
background: #80ff80;
}
#content {
background: #8080ff;
}
#footer {
background: #ff8080;
}
edit: perhaps I misunderstood, do you want everything to fit into the 200x200px box or do you want the box to increase its height to fit the content?
This can be solved by using different techniques. The first one is using media queries. Using them, you can define what your page should look like for each screen size. Secondly, there are several techniques for positioning your footer correctly (sticky footer). Thirdly, you can use different table styles or the flexbox approach to position your content correctly.