I've read awesome article and was astonished by the Flexbox Justification method. It works really well, but only when elements fit in the container entirely. I've created jsfiddle to illustrate this.
#container {
text-align: justify;
font-size: 0.1px; /* IE 9 & 10 don't like font-size: 0; */
min-width: 600px;
}
How, using this method, can I place the 6th element right after the 5th element without adding extra markup?
The sum of widths must not exceed the parent’s width, or there will be no space left to be distributed among them. Fixed (pixel) widths won’t always work on resize. If your six items are 150px each, and the container is, say, 800px in width, there’s no other way than to break into the next line.
Like the author of your article said: it’s more complicated. To stay that way, you could use calc() to have it dynamic. This is just an example:
.flex-item{
width: calc((100% / 6) - 20px); // 100% width ÷ 6 items - 20px space
}
Here’s an updated fiddle: https://jsfiddle.net/gy04jqdk/
Anyway, flexbox magic is relished best in its pure form. You can achieve the same using justify-content:space-between. To make it all work, you also have to add display:flex to the parent container. This will make it a flexbox and its immediate children flex-items. The extent of your changes might be limited to:
#container {
display: flex;
justify-content: space-between;
}
For visual illustration of element arrangement, the article at CSS-Tricks is well-known. You might be also interested in space-around, which is another value of justify-content.
Also, here’s a fiddle with a fixed width an evenly distributed space: https://jsfiddle.net/fdrgw3eu/
Assume you have a parent element that contains the three elements you would like to arrange in an equidistant manner:
.parent {
width: 100%;
}
.element1 {
width: 33.3%;
float: left;
}
.element2 {
width: 33.3%;
float: left;
left: -50%;
}
.element3 {
width: 33.3%;
float: right;
}
Related
I have three divs that contain background images (background-image: url()) but I'm having issues in making them responsive (using bootstrap) and putting spacing between them. I tried some things like width: 100% and margin: 0 auto but adding the margin property kinda removes margin and images lose spacing between each other if margin is used while padding of course doesn't work. Also for some reason I cannot add width to the images only height.
http://codepen.io/skullscream-1471533661/full/jAooJB
I'd usually google this but this has got me so frustrated that I can't even think of what to google.
Flexbox is excellent for making this sort of thing easy. Here is a great resource for flexbox to learn from.
Here I've given the parent "display: flex" to make the children flex elements. I've made the children 32% wide (leaving a 1% gap). I've set the parent to "justify-content: space-between" to tell the flex elements to leave space between each item.
On mobile I've given the parent "flex-wrap: wrap" so that if they are too wide they'll drop to the next line, and children 100% width so they span the full width of the device.
Additionally for the background images to work properly with the fluid boxes I've given them "background-size: contain" and "background-position: center center". Ideally it would be better to use actual image tags for them.
Please note that flexbox doesn't yet have full browser support (but it's still pretty good), and you'll need to add vendor prefixes as necessary.
.projects {
display: flex;
justify-content: space-between;
}
.projects > div {
flex: 0 1 32%;
background-size: contain;
background-position: center center;
}
#media screen and (max-width: 760px) {
.projects {
flex-wrap: wrap;
}
.projects > div {
flex: 0 1 100%;
margin-bottom: 20px;
}
}
There are two steps to accomplish this:
1. Change your parent div style to this:
#my-projects-section {
background-color: black;
height: 500px;
width:100%;
}
2. Add this to your child styles:
#image-one,
#image-two,
#image-three {
width: 30%;
margin: 1.66%;
height: 200px;
background-size: cover;
background-repeat: no-repeat;
transition: .2s ease-out, .2s ease-in;
}
http://codepen.io/westefan/pen/Lkoooq
Currently this is statically defined, if you would like to add a new project into the section, you have to modify the CSS. There are also options to calculate margins, but it is not yet supported: https://developer.mozilla.org/en/docs/Web/CSS/calc
Another option would be to use Javascript to count childelements and create style completely dynamical based on the amount of children.
This question already has answers here:
Flex elements ignore percent padding in Firefox
(4 answers)
Closed 7 years ago.
So, my goal is to have three square boxes whose sides expand/contract based on the size of the browser. Each box only contains one line of text, so the idea is to have a large amount of padding to fill in the extra space.
The site is built using flexbox, and I thought I had an elegant solution by using a :before to inherit the width of the parent element and use the length of it as a padding-top:
.square:before {
content:'';
padding-top:100%;
}
This works perfectly in most browsers, but I was dismayed to see Firefox is having issues. Here's the rest of the code and a JSFiddle. Any suggestions?
http://jsfiddle.net/uLqqop0q/5/
Thee CSS~~
#container {
display: flex;
width: 100%;
flex-direction: row;
justify-content: center;
max-width: 1200px;
margin: 0 auto;
}
.square {
display: flex;
flex: 1 0 auto;
margin: 10px;
border: 10px solid blue;
justify-content: center;
align-items: center;
color: #111111;
font-size: 1.7rem;
height: auto;
text-align: center;
vertical-align: middle;
}
.square:before {
content:'';
padding-top:100%;
}
EDIT: Easiest fix—just add “display:table” to the pseudo element.
That's because you use a percentage.
With block layout, percentages in paddings are resolved according to the width of the containing block, even if the paddings are in the vertical direction.
However, flexbox wanted to change this behavior, and resolve the paddings according to the width or height of the containing block, depending on the direction of the padding.
However, browsers didn't agree. Then, Firefox resolves padding-top: 100% according to the height, and Chrome does it according to the width.
In the case of Firefox, since the height of the containing block depends on the height of the content, and the padding of the pseudo-element is part of the content, the percentage can't be resolved (it would be a circular reference). Then it becomes 0. This is analogous to the case of height: 100% in a block layout where the parent has height: auto.
You can fix it by using an explicit length instead of a percentage.
I want to prevent elements in a flex container from shrinking in the dimension that is not the flex-direction. The following example has <article> elements side by side in a row. When the available vertical space is reduced, these elements do not force their flex container to display a scrollbar; instead the content overflows the element boundary.
Screenshot 1 - there is enough horizontal and vertical space to display everything:
Screenshot 2 - the reduced vertical space pushes the element border up:
Screenshot 3 - vertical space further reduced, container finally gets a scrollbar:
Screenshot 4 - without flex-shrink:0, the element widths (main flex axis) will also be reduced:
flex-shrink:0 can prevent horizontal shrinking, but how can I prevent the elements from shrinking vertically?
Giving the <article> elements overflow: auto or something similar does not give the desired result (= scrollbar on the container). Ideally, the display would look like this montage:
If I knew the elements' height in advance, I could give them a min-height, but that is not always the case.
FIDDLE: http://jsfiddle.net/twdan8u8/
HTML:
<main>
<article>article<br>article<br>article</article>
<article>article<br>article<br>article</article>
</main>
CSS:
* {
box-sizing: border-box; /* not the culprit */
}
html {
height: 100%;
}
body {
position: relative;
height: 100%;
margin: 0;
background: #999;
}
main {
overflow: auto;
background: gold;
display: flex;
height: 80%;
padding: 50px 30px;
}
article {
flex-shrink: 0;
font-size: 28px;
border: 2px solid red;
margin-right: 30px;
padding: 10px;
}
As is so often the case, I found the (or rather a) solution just when I finished writing the question. Since this might help somebody else, here's what I found out:
If the flex container is given the style align-items: flex-start, element heights are not reduced and the container gets a scrollbar when necessary (assuming a suitable overflow value).
The default for this property is "stretch". It can also be set on individual flex elements using align-self. The drawback is that the elements are now no longer equally high (i.e., they don't stretch to the full available height anymore).
I have a container div and 5 child div's with
{display: inline-block}
so they appear next to each other. Each of the child div's have a height of 20px, but the container grows to a height of 24px. Why does this happen?
Fiddle: http://jsfiddle.net/VHkNx/
Inline block elements still take care of the line-height/font-size. So adding this:
line-height: 0;
to #container will fix it.
Demo
Try before buy
Once you're using the inline-block display, your elements behaves similarly to words and letters. Whitespaces and line heights are rendered as well and it might cause some unexpected results.
One way of solving this is to give the container font-size: 0 setting (of course you can still give the child elements themselves their own font size).
jsFiddle Demo
P.S - line-height: 0 will also work.
One simple way of fixing this is to add vertical-align: top to the child elements:
.thing {
vertical-align: top;
display: inline-block;
background-color: Red;
height: 20px;
width: 18%;
margin-left: 1.25%;
margin-right: 1.25%;
}
This way, you don't need to adjust line heights or font sizes.
As noted earlier, a similar layout can be realized using floats. Both approaches are valid.
See demo at: http://jsfiddle.net/audetwebdesign/74Y2V/
Inline-block elements are placed as block on the base line of a text line, as they are inline elements, so it's the space from the base line to the bottom of the text line that takes up space.
You can use floating elements instead of inline elements:
#container {
background-color: Green;
width: 500px;
overflow: hidden;
}
.thing {
float: left;
background-color: Red;
height: 20px;
width: 18%;
margin-left: 1.25%;
margin-right: 1.25%;
}
#first {margin-left: 0px;}
#last {margin-right: 0px;}
Demo: http://jsfiddle.net/VHkNx/2/
Easiest way is not to give them display: inline-block, but use float: left; . All elements will float next to each other. Good luck!
I'm trying to create some evenly spaced columns (an ol), with the columns themselves being fixed width.
So far, I've managed to achieve the desired effect by using table layout, and nesting an additional element inside the list item.
HTML:
<ol>
<li><div></div></li>
<li><div></div></li>
<li><div></div></li>
<li><div></div></li>
<li><div></div></li>
</ol>
CSS:
ol {
display: table;
width: 100%;
}
li {
display: table-cell;
}
div {
margin: 0 auto;
width: 100px;
height: 250px;
}
This works great, but has the following 2 shortcomings:
As you can see in the demo, the first & last columns don't line up flush with the parent's outer edges.
This can't really be used responsively. The only thing you can do at smaller widths is stack them, but I'd like to split them (2 or 3 per row).
Is what I'm after even possible in CSS alone? I know there are a plethora of ways to accomplish this in JS, but I'm after a CSS-only solution.
P.S. I don't care about IE7-, but I do need to support IE8. CSS3 selectors are OK though, since I'm anyhow using selectivizr in the project (I know that's JS ;-)).
It seems appropriate for you to recycle "how to *really* justify a horizontal menu". Basically the behaviour you're describing is that of inline-block elements of identical width having text-align:justify applied:
ol {
/*force the desired behaviour*/
text-align: justify;
/*remove the minimum gap between columns caused by whitespace*/
font-size: 0;
}
li {
/*make text-align property applicable*/
display: inline;
}
/*force "justify" alignment that requires text to be at least over 2 lines*/
ol:after {
content: "";
display: inline-block;
position: relative;
width: 100%;
height: 0;
}
div {
display: inline-block;
width: 100px;
height: 250px;
}
Working fiddle.
NB: you may have to re-apply desired font-size and text-align to descendants of ol depending on the reset you're using (i.e. to prevent these properties from being inherited)
Ok my first thought would be to use media queries to gain a responsive approach for how many you want to show per row on differing screen sizes and my second would be to use
box-sizing:border-box;
-moz-box-sizing:border-box;
-webkit-box-sizing:border-box;
this will stop the paddings you may put in later adding onto the box model size.
Hope this is close to what you are after.