Flex column replacement for unsupported browsers - css

I've been trying to get my head managing a specific layout without using flexbox (specifically flex-direction: column). I'm almost certain this has been asked elsewhere but for the life of me I haven't been able to find it, so I'm very sorry if it has and will gladly close if anyone can show me it answered somewhere else.
The problem is this: given an arbitrary number of divs, all but one of which have a fixed height, how can I lay them out in a column such that the remaining element fills 100% of the height available to it, after the others have been taken into account?
It looks like (Codepen):
div.container
div.cell.fixedheight
div.cell.fillheight
div.cell.fixedheight
div.cell.fixedheight
div.cell.fixedheight
This is pretty easily achievable using flexbox with something like:
.container {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
}
.fixedheight {height: 20px;}
.fillheight {flex: 1;}
But I'm essentially not in a position to use flexbox, since supporting older browsers is necessary here.
Edit when I say I can't use flexbox, I mean not even vendor prefixes :(

You can achieve it with table layouts, with a light wrapper of row-style and cell-style divs. If anyone knows of a solution that doesn't involve an extra wrapper in the markup I'll gladly take it :)
See the approach on this Codepen but I'll put the relevant code here:
div.container
div.row.fixedheight
div.cell
div.row.fillheight
div.cell
div.row.fixedheight
div.cell
div.row.fixedheight
div.cell
div.row.fixedheight
div.cell
and then the CSS:
.container {
display: table;
}
.row {
display: table-row;
}
.row.fixedheight {
height: 20px;
}
.row.fillheight {}
.cell {
display: table-cell;
}
The .cells will accept very little further styling (margins etc) so they'll need to act as a wrapper for whatever richly styled divs you want to put inside them.
Also note that multiple .fillheights will share the available height between them equally.
Also note that the fixed height rows are not in fact fixed height - the 20px will be used as effectively a min-height, but the cell will wrap whatever it has in it. I've been accepting this and setting height: 0 on the cell and height: 20px on an inner div which isn't table-styled.

Related

3 rows, 100% height flexbox layout doesn't work on android

please take a look:
https://jsfiddle.net/sgtooLnb/1/
so basically a flexbox column layout and an html structure like this (I must add some more code for the parser..):
<header>The header content goes here.</header>
<div class="content">The main content goes here.</div>
<footer>The footer content goes here.</footer>
On android (4.4.2), a layout like this seems not to work. Footer will always stick on bottom, while overflowing content will be below the footer.
Sadly, you cannot see this behavour from jsfiddle, but maybe some of you have had the same problem before.
Any solution?
Ok, by better indagating this and this I found out that the problem is this even if Android is not mentioned on the affected browsers list. So, my solution was to add flex-shrink: 0 to the content:
body{
display: flex;
flex-direction: column;
height: 100%;
}
.main-content{
flex: 1 0 auto; // flex-shrink:0 > android 4.4.2 fix (and some other browsers too)
}
It's also good to assign some kind of flex property to header and footer. I noticed on Android 442 that otherwise the bg color was gone:
.main-header,
.main-footer{
flex: none; // or flex something.
}
Also please note that I'm using Autoprefixer. Otherwise, you should not use the shortcut on main-content (IE shit-fix):
.main-content{
flex-grow: 1;
flex-shrink:0;
flex-basis:auto;
}
Finally, to the one that downvoted this thread: you had the relevant code on the jsfiddle. Also, if you really knew the subject, you didn't need any code. And if you didn't know the subject, you shouldn't downvote anything.
Now please downvote again, so this material won't help anyone. Is this the main stackoverflow target?
The children elements of your flex element (body) need to be display: flex as well. If you add the style
body > * {
display: flex;
}
I believe you'll get the desired result

Alignment of buttons

I've been trying to create this webpage off a course from udemy. If you take a look at the picture you'll notice that at the bottom at the GET INVOLVED section, my buttons and texts are not aligned. I need advice on how to make these columns even so that the buttons are aligned. Should I use margin/padding or is there another way?
Assuming that the description is written in a div try giving min-height to that div
An age old question indeed: how to make 2+ divs the same height?
There have been many hacks and workarounds, but nowadays flexbox comes to the rescue.
#wrapper { /* Something around those 3 columns */
display: flex;
}
.pill { /* Every column has this class */
flex: 1;
align-items: center;
display: flex;
justify-content: space-between;
flex-direction: column;
}
Example on JSFiddle
Before using this example, I would recommend reading something about flexbox, maybe this exhaustive guide.
As stated below in the comments, there are some issues with cross-browser support at the moment. More details here

How to specify an element after which to wrap in css flexbox? [duplicate]

This question already has answers here:
How to specify line breaks in a multi-line flexbox layout?
(9 answers)
Closed 3 years ago.
I don't think this is part of the flexbox standard yet, but is there maybe a trick to suggest or force wrapping after a certain element? I'd like to respond to different page sizes and wrap a list differently without extra markup, so that rather than having (for example) orphaned menu items on the next line, I break in the middle of the menu.
Here's the starting html:
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
<li>Five</li>
</ul>
And css:
ul {
display: flex;
flex-wrap: wrap;
}
I'd love something like the following:
/* inside media query targeting width */
li:nth-child(2n) {
flex-break: after;
}
See the jsfiddle for a more complete setup: http://jsfiddle.net/theazureshadow/ww8DR/
You can accomplish this by setting this on the container:
ul {
display: flex;
flex-wrap: wrap;
}
And on the child you set this:
li:nth-child(2n) {
flex-basis: 100%;
}
ul {
display: flex;
flex-wrap: wrap;
list-style: none;
}
li:nth-child(4n) {
flex-basis: 100%;
}
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
This causes the child to make up 100% of the container width before any other calculation. Since the container is set to break in case there is not enough space it does so before and after this child. So you could use an empty div element to force the wrap between the element before and after it.
=========================
Here's an article with your full list of options: https://tobiasahlin.com/blog/flexbox-break-to-new-row/
EDIT: This is really easy to do with Grid now: https://codepen.io/anon/pen/mGONxv?editors=1100
=========================
I don't think you can break after a specific item. The best you can probably do is change the flex-basis at your breakpoints. So:
ul {
flex-flow: row wrap;
display: flex;
}
li {
flex-grow: 1;
flex-shrink: 0;
flex-basis: 50%;
}
#media (min-width: 40em;){
li {
flex-basis: 30%;
}
Here's a sample: http://cdpn.io/ndCzD
============================================
EDIT: You CAN break after a specific element! Heydon Pickering unleashed some css wizardry in an A List Apart article: http://alistapart.com/article/quantity-queries-for-css
EDIT 2: Please have a look at this answer: Line break in multi-line flexbox
#luksak also provides a great answer
There is part of the spec that sure sounds like this... right in the "flex layout algorithm" and "main sizing" sections:
Otherwise, starting from the first uncollected item, collect
consecutive items one by one until the first time that the next
collected item would not fit into the flex container’s inner main
size, or until a forced break is encountered. If the very first
uncollected item wouldn’t fit, collect just it into the line. A break
is forced wherever the CSS2.1 page-break-before/page-break-after
[CSS21] or the CSS3 break-before/break-after [CSS3-BREAK] properties
specify a fragmentation break.
From http://www.w3.org/TR/css-flexbox-1/#main-sizing
It sure sounds like (aside from the fact that page-breaks ought to be for printing), when laying out a potentially multi-line flex layout (which I take from another portion of the spec is one without flex-wrap: nowrap) a page-break-after: always or break-after: always should cause a break, or wrap to the next line.
.flex-container {
display: flex;
flex-flow: row wrap;
}
.child {
flex-grow: 1;
}
.child.break-here {
page-break-after: always;
break-after: always;
}
However, I have tried this and it hasn't been implemented that way in...
Safari (up to 7)
Chrome (up to 43 dev)
Opera (up to 28 dev & 12.16)
IE (up to 11)
It does work the way it sounds (to me, at least) like in:
Firefox (28+)
Sample at http://codepen.io/morewry/pen/JoVmVj.
I didn't find any other requests in the bug tracker, so I reported it at https://code.google.com/p/chromium/issues/detail?id=473481.
But the topic took to the mailing list and, regardless of how it sounds, that's not what apparently they meant to imply, except I guess for pagination. So there's no way to wrap before or after a particular box in flex layout without nesting successive flex layouts inside flex children or fiddling with specific widths (e.g. flex-basis: 100%).
This is deeply annoying, of course, since working with the Firefox implementation confirms my suspicion that the functionality is incredibly useful. Aside from the improved vertical alignment, the lack obviates a good deal of the utility of flex layout in numerous scenarios. Having to add additional wrapping tags with nested flex layouts to control the point at which a row wraps increases the complexity of both the HTML and CSS and, sadly, frequently renders order useless. Similarly, forcing the width of an item to 100% reduces the "responsive" potential of the flex layout or requires a lot of highly specific queries or count selectors (e.g. the techniques that may accomplish the general result you need that are mentioned in the other answers).
At least floats had clear. Something may get added at some point or another for this, one hopes.
Setting a min-width on child elements will also create a breakpoint. For example breaking every 3 elements,
flex-grow: 1;
min-width: 33%;
If there are 4 elements, this will have the 4th element wrap taking the full 100%. If there are 5 elements, the 4th and 5th elements will wrap and take each 50%.
Make sure to have parent element with,
flex-wrap: wrap
The only thing that appears to work is to set flex-wrap: wrap; on the container and them somehow make the child you want to break out after to fill the full width, so width: 100%; should work.
If, however, you can't stretch the element to 100% (for example, if it's an <img>), you can apply a margin to it, like width: 50px; margin-right: calc(100% - 50px).

CSS Sticky Header/Footer and Fully Stretched Middle Area?

With CSS, how can i simply get a page with sticky header and footer which are appearing forever, whenever the page is scrolling or not. I found some sample online, but what i additional want is, the middle content area should be a 100% stretched area between header and footer whatever the browser size is.
I mean, most of the Samples i found, are making Header and Footer sticky correctly.., but these are just floating and actually covering the Top and Bottom parts of the 'middle' content area. That's not what i really want.
Can use absolute position for all 3 elements.
#header,#footer,#content { position:absolute; right:0;left:0}
#header{
height:100px; top:0;
}
#footer{
height:100px; bottom:0;
}
#content{
top:100px;
bottom:100px;
overflow:hidden; /* use this if don't want any window scrollbars and use an inner element for scrolling*/
}
DEMO: http://jsfiddle.net/RkX8B/
The solutions presented above work for very simple layout with no border, margin, and/or padding. Many, many solutions that you'll find on the Net will work for this.
However, almost all solutions fall completely apart if you simply add border, margin, and/or padding to any or all of your Divs.
Flex Boxes (CSS display:flex;) are incredibly powerful for this, and they work perfectly with any combination of border, margin, and/or padding.
They can portion your screen space into as many Divs as you need, using fixed size, percentage size, or "whatever's left" for each inner Div. These can be in any order, so you aren't limited to just headers and/or footers. They can also be used horizontally instead of vertically, and can next.
So you could have, say, a fixed-size header, a 20% footer, and a "whatever's left" client area between them that sizes dynamically. Inside that client area, in turn, you could have, say, a percentage-width menu bar at the left edge of the client area, a fixed-width vertical divider next to that, and a client area that takes up "whatever's left" to the right of that.
Here's a Fiddle to demonstrate all of this. The relevant CSS is remarkably simple.
CSS Flex Box (display:flex;) Demonstration with Borders/Margin/Padding
For instance, here are two CSS classes that create containers that will flow their contained Divs either horizontally or vertically, respectively:
.HorFlexContainer {
display: flex;
flex-direction: row;
flex-wrap: wrap;
flex: 1; /* this essentially means "use all parent's inner width */
}
.VertFlexContainer {
display: flex;
flex-direction: column;
flex-wrap: wrap;
flex: 1; /* this essentially means "use all parent's inner height */
}
The Fiddle above really shows it all off, though.
For reference, see this excellent article by Chris Coyier:
Flexbox Tutorial
Hope this all helps!
You're probably looking for the "position: fixed;" property, and setting the header to top: 0; and the footer to bottom: 0; You might also consider some padding to your "content area" to account for that header and footer space...
From the top of my head you would have something like:
header { position: fixed; top: 0; height: 100px; }
footer { position: fixed; bottom: 0; height: 100px; }
#container { padding: 100px 0; }
If you're using some kind of background on your container and want to stretch it, a height: 100%; should do...
I've never found a good way to use this kind of layout though... =\

Is it possible to set the width of a set of elements to add up to 100%?

Probably not the best title I've ever written, but I find it hard to formulate this question well. I'm working on a div that should cover 100% of the parent (could be body). This div should have a variable number of children, so every time the page is refreshed the children count can vary from one to ten, maybe more.
I want these children to all be equally wide and have a percentage width. So if there are five children, each child should have width: 20%. If there are two children, they should have width: 50%. I could do this with JavaScript, but I'd really prefer keeping all layout stuff in the css.
Is there a way to accomplish this without using tables?
Use display: table, display: table-cell, and table-layout: fixed.
See: http://jsfiddle.net/thirtydot/ZKXrM/
table-layout: fixed is to equally distribute the available width between any cells without an assigned width.
This works in all modern browsers. It doesn't work in IE7. If you need this to work in IE7, either use JavaScript to polyfill, or use a real <table>.
CSS:
.container {
display: table;
table-layout: fixed;
width: 100%;
}
.container > div {
display: table-cell;
border: 1px dashed red;
}
HTML:
<div class="container">
<div>1</div>
<div>2</div>
..
</div>​
You could define something like
div#contains2 div
{
width: 50%;
}
div#contains3 div
{
width: 33%;
}
and so on, then apply the appropriate class to the parent div.
That said, is there a good reason why you're avoiding a table, but trying to recreate how a table works? Sure, it may not be the absolute nicest "sleep-well-at-night" way to make a page, but if the table does the job how you want it doing, and you can't think of anything else that does, go with the table.
The bottom line is that you have essentially 3 options for automatic same-width columns:
Tables, which do it out of the box and will work cross-browser with no major issues
jQuery, which will probably work cross browser, provided the user has JS enabled
CSS like I suggested above, which adds bloat to your CSS file, and fluff to your markup
You can divide the total width (100%) into the number of items (X). So W = 100/X and W=Width.

Resources