I would like to have layout of div elements that looks like below:
If screen is large enough then there is many blocks in the single row.
For example, I would like to have minimum width of each block set to 250px.
So on large screens I can have the following for such elements. On the right is the map (closable), if user hide it then there will be 6 blocks in the row.
Next when I shrink the browser window horizontally this all block doesn't fit in the row so they move to the next row. Ok this works now in that way that they go do second row, but they leave space between div blocks and the map. Like on the below image.
I would like to have such layout where if 4 blocks doesn't fit the space then ok there is 3 blocks but they equally fill the remaining space (without this remaining yellow space). See pictures below.
Then when browser windows shrinks more it should look like below
And on mobile devices and very narrow browser windows:
Ok I could achieve something like this using such CSS style:
#parent {
display: flex;
flex-wrap: wrap;
}
.child {
width: calc(33% - 15px);
margin-left: 10px;
margin-top: 10px;
margin-bottom: 20px;
min-width: 250px;
}
then I should manually change this using media queries:
calc(25% - 15px) //lg
calc(33% - 15px) //md
calc(50% - 15px) //sm
calc(100% - 15px) //xs
maybe even this when map disappears
calc(16.667% - 15px) //lg+no map
Ok FLEX isn't so backward-compatible so I could play even more and do something like this:
#parent {
}
.child {
width: calc(33% - 15px);
margin-left: 10px;
margin-top: 10px;
margin-bottom: 20px;
min-width: 250px;
float: left;
}
then also change this width depending on screen size manually
and add clear: left after last element using
.block-offer:nth-last-child(1):after {
clear: left;
}
or before other elements make some other clearfix
or even (is it necessery?) add clear: left after each row using:
.block-offer:nth-child(4n+1) {
clear:left;
}
.block-offer:nth-child(3n+1) {
clear:left;
}
.block-offer:nth-child(2n+1) {
clear:left;
}
.block-offer:nth-child(1n+1) {
clear:left;
}
like with this width: calc() depending on screen size and divs witdh
But then I need to use many media queries and I would like to wrap this CSS in some angular 2+ component and have there only such things like:
<blocks-container max-cols="6">
<block min-width="250px"></block>
<block min-width="250px"></block>
...
</blocks-container>
I think that using #media queries will improve a little this behaviour but my components will tightly coupled with screen size and I think there wasn't as generic as I would like them to be to flexibly specify max-cols and min-widths.
Here's one possible solution, which combines CSS flexbox and grid:
body {
display: flex; /* 1 */
}
article { /* 2 */
flex: 1; /* 2 */
margin-right: 10px;
display: grid; /* 3 */
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); /* 4 */
grid-auto-rows: 100px; /* 5 */
grid-gap: 10px; /* 6 */
}
map {
min-height: 200px; /* 7 */
width: 250px;
background-color: orangered;
}
#media (max-width: 800px) { /* 8 */
map { display: none; }
}
section {
background-color: lightblue;
border: 2px solid gray;
}
<article>
<section></section>
<section></section>
<section></section>
<section></section>
<section></section>
<section></section>
</article>
<map></map>
jsFiddle
Notes:
Create a flex container with two flex items.
The first item (article) holds the wrapping blocks (section). It's set to flex: 1 to consume all available width.
The first item is made into a grid container, so grid properties can be
applied to the blocks.
See below.
The grid-auto-rows property sets the height of automatically generated rows.
The grid-gap property is a shorthand for grid-column-gap and grid-row-gap. This rule set a 10px gap between grid items.
The second flex item is the map (map), which is aligned right due to flex: 1 on its sibling.
The media query removes the map, to simulate user behavior.
The auto-fill function allows the grid to line up as many grid tracks (columns or rows) as possible without overflowing the container. This can create similar behavior to flex layout's flex-wrap: wrap.
The minmax() function sets a minimum and maximum size range for a grid track. In the code above, the width of column tracks will be a minimum of 250px and maximum of whatever free space is available (1fr). This prevents the display of empty space.
The fr unit represents a fraction of the available space. It is similar to flex-grow in flex layout.
Browser Support for CSS Grid
Chrome - full support as of March 8, 2017 (version 57)
Firefox - full support as of March 6, 2017 (version 52)
Safari - full support as of March 26, 2017 (version 10.1)
Edge - full support as of October 16, 2017 (version 16)
IE11 - no support for current spec; supports obsolete version
Here's the complete picture: http://caniuse.com/#search=grid
You could refer this as an example, you could do that using flex or using media query to change style for elements at different break points as below, this gives more understanding of what changes are made.
Check this jsFiddle - https://jsfiddle.net/sjf5ms08/
#box{
width:100%;
height:auto;
}
#box > .b1, .b2, .b3, .b4, .b5, .b6{
width:33%;
height:150px;
background:red;
display:inline-block;
}
#media screen and (max-width: 1280px){
#box > .b1, .b2, .b3, .b4, .b5, .b6{
width:250px;
height:150px;
margin-bottom:10px;
background:blue;
}
}
#media screen and (max-width: 940px){
#box > .b1, .b2, .b3, .b4, .b5, .b6{
width:33%;
margin-bottom:10px;
background:yellow;
}
}
#media screen and (max-width: 760px){
#box > .b1, .b2, .b3, .b4, .b5, .b6{
width:49%;
margin-bottom:10px;
background:green;
}
}
<div id="box">
<div class="b1">1</div>
<div class="b2">2</div>
<div class="b3">3</div>
<div class="b4">4</div>
<div class="b5">5</div>
<div class="b6">6</div>
</div>
If you want to use the float method, you should do sth like :
FIDDLE
HTML:
<div class="col">
<div class="content">
<p>Content</p>
</div>
</div>
CSS:
/* complete with your style */
.col { display:block; width:25%; border-sizing:border:box; float:left; padding:10px; }
#media (max-width: 1280px) {
.col { width:33%; }
}
#media (max-width: 1024px) {
.col { width:50%; }
}
#media (max-width: 768px) {
.col { width:100%; }
}
If you want to use the flex method, order your html by row, then use flex-wrap:wrap; and width:250px or min-width:250px: width:25%, and play with the media queries as above
You can try applying flex on the cards (flex-grow/ flex-shrink/ flex-basis)
body {
margin: 0;
}
.parent {
width: 100vw;
min-height: 100vh;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.child:nth-child(2n+1) {
background: rgb(0, 0, 255);
}
.child:nth-child(2n+2) {
background: rgb(255, 255, 255);
}
.child:nth-child(2n+3) {
background: rgb(244, 241, 194);
}
.child {
margin: 10px 10px 20px 0;
min-width: 250px;
height: 300px;
background: green;
box-sizing: border-box;
border: 1px solid black;
flex: 1 1 250px;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
Fiddle : https://jsfiddle.net/0jc93hqn/
Related
When browser width becomes under 600px, I'd like such a position change, thanks to a media query :
It seems that this would need to swap div position. Is this possible with CSS?
* { padding: 0; margin: 0; }
#a { float: left; background-color: red; width: 150px; }
#b { background-color: blue; }
#c { float: right; width: 40%; background-color: yellow; }
#media (max-width: 600px) {
/* ... */
}
<div>
<div id="a">a</div>
<div id="c">c</div>
<div id="b">b</div>
</div>
You only need to reset the float or width properties.
Do mind the BFC block formating context when you deal with floating and non floatting elements.
http://www.sitepoint.com/understanding-block-formatting-contexts-in-css/
* {
padding: 0;
margin: 0;
}
#a {
float: left;
background-color: red;
width: 150px;
}
#b {
background-color: blue;
}
#c {
float: right;
width: 40%;
background-color: yellow;
}
#media (max-width: 600px) {
#c {
width: 100%;
}
}
<div>
<div id="a">a float</div>
<div id="c">c float or not</div>
<div id="b">b</div>
</div>
Yes, it's possible with CSS. In fact, it's quite easy with flexbox, which is designed for such a task.
* {
padding: 0;
margin: 0;
}
#container {
display: flex; /* establish flex container */
}
#a {
flex: 0 0 150px; /* don't grow, don't shrink, fixed at 150px width */
background-color: red;
}
#b {
flex: 1; /* consume all available free space in the row */
background-color: aqua;
}
#c {
flex: 0 0 40%; /* don't grow, don't shrink, fixed at 40% width */
background-color: yellow;
}
#media (max-width: 600px) {
#container { flex-wrap: wrap; } /* allow flex items to wrap */
#b { flex-basis: calc(100% - 150px); } /* take full width less width of #a */
#c { flex-grow: 1; } /* consumer all available free space in the row */
}
<div id="container"><!-- children ordered chronologically; no need to reverse order -->
<div id="a">a</div>
<div id="b">b</div>
<div id="c">c</div>
</div>
To learn more about flexbox visit:
Methods for Aligning Flex Items
Using CSS flexible boxes ~ MDN
A Complete Guide to Flexbox ~ CSS-Tricks
What the Flexbox?! ~ YouTube video tutorial
Benefits of flexbox:
minimal code; very efficient
centering, both vertically and horizontally, is simple and easy
equal height columns are simple and easy
multiple options for aligning flex elements
it's responsive
unlike floats and tables, which offer limited layout capacity because they were never intended for building layouts, flexbox is a modern (CSS3) technique with a broad range of options.
Browser support:
Flexbox is supported by all major browsers, except IE 8 & 9. Some recent browser versions, such as Safari 8 and IE10, require vendor prefixes. For a quick way to add all the prefixes you need, use Autoprefixer. More details in this answer.
I have 3 boxes that are currently floated left of each other,
https://jsfiddle.net/2owu0k7s/
When viewing on a smartphone I want the width of the boxes to be near full screen, and the height of each box to be the same height has the viewport. Is this possible to do?
I have tried doing this within a media query,
.box {
float:none;
width:95%;
margin:0 auto 20px;
height:95%;
}
But on my iphone 6s I can still see more than 1 box and 5% of another.
When viewing on a smartphone I want the width of the boxes to be near full screen, and the height of each box to be the same height has the viewport. Is this possible to do?
With a media query and flexbox it is possible (and quite simple, in fact). Here's the smartphone view:
body {
display: flex;
flex-direction: column;
margin: 0;
padding: 0;
}
.box {
width: 100%;
height: 100vh;
box-sizing: border-box;
border: 3px solid red;
}
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
Revised Fiddle
.box {
width:350px;
height:50vh;
border:1px solid red;
float:left;
margin-right:10px;
}
#media screen and (max-width: 740px) {
.box {
float:none;
width:95%;
margin:0 auto 20px;
height:96vh;
}
}
Write an media query and
Give the height measurements using 'vh' -vertical height.
100vh means full screen-height.
How can I create a responsive arrangement of three divs, such that:
when the viewport is narrow, the three divs appear one atop the other
when the viewport is average, the first div appears full width atop the other two, which are side-by-side and have equal height
when the viewport is wide, the three divs appear side-by-side with equal height
I would like the solution to be broadly supported by browsers.
I've tried a number of media query based strategies, as follows:
To achieve #1, I style each div as display:block
To achieve #2, I style the green and blue divs as display:table-cell and created a container div styled with display:table.
However, if I create another container div for all three elements and style it with display:table, neither of the following approaches work:
Setting all divs to display:table-cell - because the red table cell and the other two are intervened by the smaller container div
Setting the red div and the smaller container divs to display:table-cell - because the smaller container div still needs to be set to display:table for the sake of the green and blue divs inside it.
It's all a bit hard to explain, but I guess you have the idea. Any help would be greatly appreciated.
Thanks!
Edit: I don't want to set the height of any div manually. It should be dictated by its content
What you are trying to achieve is fairly difficult using display: table because of just the issue you ran into: containers are required and the configuration is not that flexible due to the way tables' strict requirements.
I suggest you use flexbox which has fairly good browser coverage now: http://caniuse.com/#feat=flexbox
Here is a good example of how to get equal height rows using flexbox: http://osvaldas.info/flexbox-based-responsive-equal-height-blocks-with-javascript-fallback
I know #fauxserious already posted a very similar answer, but I'll post mine anyways because it's a bit different.
This doesn't use a table, nor the ::before or ::after CSS pseudo-elements.
div#div1 {
background-color: red;
}
div#div2 {
background-color: green;
}
div#div3 {
background-color: blue;
}
div {
box-sizing: border-box;
padding: 20px;
float: left;
margin: 1%;
width: 31%;
}
#media screen and (max-width: 750px) {
div#div1 {
width: 98%;
}
div#div2, div#div3 {
width: 48%;
}
}
#media screen and (max-width: 500px) {
div {
width: 98% !important;
}
}
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
(It's best to see the above snippet if you open it in a new tab / window and resize it.)
See working example on JSFiddle.net.
EDIT See updated snippet. If you remove the height property of the divs (and replace it with padding so that you can see it even when it's empty), then the height will be determined by its content.
Edit: sorry I missed the equal height part.
You are trying to make squares so let me code and then explain. I'm going to make this a list to help identify things. Assume the ul has been reset (no margin, padding or style-type).
<ul>
<li>
<div>
</div>
</li>
<li>
<div>
</div>
</li>
<li>
<div>
</div>
</li>
</ul>
Here's the CSS to make everything squares.
li{
position:relative;
width:33%;
padding-top:33%;
}
li > div{
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
height:100%;
width:100%;
}
You'll notice the padding to be equal to the width. Padding percentage no matter where it's used is based on the parent element's width (margin also works this way). Even if you use it on the top or bottom.
Now with that we can get to positioning with CSS
ul:before, ul:after{
content:"";
display:table;
}
ul:after{
clear:both;
}
li{
position:relative;
width:33%;
padding-top:33%;
float:left;
}
#media screen and (max-width:800px){
li{
width:50%;
padding-top:50%;
}
li:first-child{
width:100%;
padding-top:0; /* Not sure what height you'd want here*/
}
}
#media screen and (max-width:400px){
li{
width:100%;
padding-top:100%;
}
}
I was unsure of why you wanted to use display: table;, however I did something a little different but will look like the images you posted above.
HTML:
<div class="container">
<div class="box box1"></div>
<div class="box box2"></div>
<div class="box box3"></div>
</div>
CSS:
.container {
width: 90%;
margin: 0 auto;
}
.box {
width: 32.3333%;
float: left;
height: 200px;
margin: .5%;
}
.box1 {
background-color: #ff4034;
}
.box2 {
background-color: #22ff62;
}
.box3 {
background-color: #24a6ff;
}
#media screen and (max-width: 900px){
.box:first-child {
width: 99%;
}
.box:nth-child(n + 2){
width: 49%;
}
}
#media screen and (max-width: 436px){
.container .box {
width: 99%;
clear: both;
margin-bottom: 10px;
}
}
Result: Your images above
How about using flex?
.parent {
border: 1px solid #555;
display: flex;
flex-flow: row wrap;
}
.dual {
display: flex;
flex-flow: row wrap;
flex: 2 2 550px;
}
.item {
padding: 20px;
margin: 10px;
flex: 1 1 200px;
min-width: 200px;
}
<div class="parent">
<div class="item" style="background-color: red">red</div>
<div class="dual">
<div class="item" style="background-color: green; flex: 1 1 100px">green</div>
<div class="item" style="background-color: blue; flex: 1 1 100px">blue</div>
</div>
</div>
I had to tweak the sizes a little due to padding and margins, like ".dual" being 550px instead of 400px. Also if the combined items are the same size they will show as two rows in the second column sometimes when shrinking so I made them smaller. Make it full page when you run the snippet or check out the fiddle link which is easier to resize has some extra text showing the blue and green boxes keep the same height in layout 2.
I wanted the behaviour of inline-block and float together of several divs in a responsive container (% width), where:
float effect:
1a. it would have divs left and right aligned
1b. when the window width shrinks - the space between the left and right divs would also shrink
inline-block effect:
2a. all the divs would be in the same line
2b. when the window width shrinks - it will hide the divs (usually starting on the right)
Examples:
when the window is larger that the divs:
when the window is smaller that the divs:
2a. the wanted effect
2b. the wrong effect
Here is a code example of what I got so far (which only simulates the float effect (1) and effect in same line (2b) but missing effect when shrinking the window width (3b) ), with a demo:
.item1 {background-color: red;}
.item2 {background-color: yellow;}
.item3 {background-color: blue;}
#container {
width: 95%;
height: 50px; /* not sure if is needed */
}
#container div {
display: inline-block; /* does nothing with floats */
width:100px;
height: 50px;
}
.left {float: left;}
.right {float: right;}
<div id="container">
<div class="item1 left">item1</div>
<div class="item2 right">item2</div>
<div class="item3 right">item3</div>
</div>
Notes:
The container has a % value (to be a bit responsive).
the width of the divs (items) is supposed to have a fixed width (to have a logo image, a menu, and some icons (more images), ...)
in the example, I've also added the inline-block just to show that it does not works with it
the example only uses 3 divs (1 left and 2 right), but if possible I preferred a solution where I could have more without changing too much of code.
(I want to avoid fixed position (like right:20px or 20%) to be easier to add new items.)
was supposed to find a solution using only html and css (or html5 and css3) (avoiding JavaScript).
You should take a look at bootstraps grid system. It would save you a lot of time. http://getbootstrap.com/2.3.2/scaffolding.html#gridSystem
May be it is not fully what you want, but it gets close:
use flex for the container, and hide the second row.
and play with flex-shrink, flex-basis, max-width and margin
.container {
width: 80%;
display: flex;
flex-wrap: wrap;
height: 100px;
margin-bottom: -100px;
border: solid 1px red;
overflow: hidden;
}
.container div {
height: 100px;
border: solid 1px;
}
.left {
flex: 200px 0 0;
background-color: lightgreen;
margin-right: auto;
}
.right {
flex: 100px 1 1;
background-color: yellow;
max-width: 200px;
}
.disappears {
flex: 200px 0 1;
background-color: papayawhip;
}
<div class="container">
<div class="left">left</div>
<div class="right">right</div>
<div class="disappears">dis</div>
<div class="disappears">dis</div>
</div>
You need to add overflow:hidden; to your #container
#container {
width: 95%;
height: 50px; /* not sure if is needed */
overflow: hidden;
}
After more research and tests, I finally come up with a solution, with a demo:
.item1 {background-color: red;}
.item2 {background-color: yellow;}
.item3 {background-color: blue;}
#container {
width: 95%;
display: flex;
justify-content: space-between;
}
/* affects container_left and container_right divs */
#container > div {
display: flex;
}
/* affects items */
#container > div > div {
width: 100px;
min-width: 100px; /* to avoid shrinking in IE 11*/
height: 50px;
}
#container, #container > div {
/* reading from right to left (RTL)*/
/* flex-direction: row-reverse; */
}
<div id="container">
<div class="container_left">
<div class="item1">item1</div>
</div>
<div class="container_right">
<div class="item2">item2</div>
<div class="item3">item3</div>
</div>
</div>
Notes:
It does the effects asked, at least in Firefox (v 37.0.2) and Internet Explorer (IE 11).
In chrome (v 42.0.2311.135 m) it doesn't respect the min-width. Maybe there's some way around it that I didn't realize.
Changed the html to put 2 containers for left and right items, (and if needed you could also add a middle container). And in css using the flex property with the "justify-content: space-between" to align the containers.
New items can be easily added to the right positions (just in html) without the need to use a grid system.
Also added some css code to uncomment if you want to reverse the item order (in right to left languages).
I have a fluid width container DIV.
Within this I have 4 DIVs all 300px x 250px...
<div id="container">
<div class="box1"> </div>
<div class="box2"> </div>
<div class="box3"> </div>
<div class="box4"> </div>
</div>
What I want to happen is box 1 to be floated left, box 4 to be floated right and box 2 and 3 to be spaced evenly between them. I want the spacing to be fluid as well so as the browser is made smaller the space becomes smaller also.
See: http://jsfiddle.net/thirtydot/EDp8R/
This works in IE6+ and all modern browsers!
I've halved your requested dimensions just to make it easier to work with.
text-align: justify combined with .stretch is what's handling the positioning.
display:inline-block; *display:inline; zoom:1 fixes inline-block for IE6/7, see here.
font-size: 0; line-height: 0 fixes a minor issue in IE6.
#container {
border: 2px dashed #444;
height: 125px;
text-align: justify;
-ms-text-justify: distribute-all-lines;
text-justify: distribute-all-lines;
/* just for demo */
min-width: 612px;
}
.box1,
.box2,
.box3,
.box4 {
width: 150px;
height: 125px;
vertical-align: top;
display: inline-block;
*display: inline;
zoom: 1
}
.stretch {
width: 100%;
display: inline-block;
font-size: 0;
line-height: 0
}
.box1,
.box3 {
background: #ccc
}
.box2,
.box4 {
background: #0ff
}
<div id="container">
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
<div class="box4"></div>
<span class="stretch"></span>
</div>
The extra span (.stretch) can be replaced with :after.
This still works in all the same browsers as the above solution. :after doesn't work in IE6/7, but they're using distribute-all-lines anyway, so it doesn't matter.
See: http://jsfiddle.net/thirtydot/EDp8R/3/
There's a minor downside to :after: to make the last row work perfectly in Safari, you have to be careful with the whitespace in the HTML.
Specifically, this doesn't work:
<div id="container">
..
<div class="box3"></div>
<div class="box4"></div>
</div>
And this does:
<div id="container">
..
<div class="box3"></div>
<div class="box4"></div></div>
You can use this for any arbitrary number of child divs without adding a boxN class to each one by changing
.box1, .box2, .box3, .box4 { ...
to
#container > div { ...
This selects any div that is the first child of the #container div, and no others below it. To generalize the background colors, you can use the CSS3 nth-order selector, although it's only supported in IE9+ and other modern browsers:
.box1, .box3 { ...
becomes:
#container > div:nth-child(odd) { ...
See here for a jsfiddle example.
The easiest way to do this now is with a flexbox:
http://css-tricks.com/snippets/css/a-guide-to-flexbox/
The CSS is then simply:
#container {
display: flex;
justify-content: space-between;
}
demo: http://jsfiddle.net/QPrk3/
However, this is currently only supported by relatively recent browsers (http://caniuse.com/flexbox).
Also, the spec for flexbox layout has changed a few times, so it's possible to cover more browsers by additionally including an older syntax:
http://css-tricks.com/old-flexbox-and-new-flexbox/
http://css-tricks.com/using-flexbox/
If css3 is an option, this can be done using the css calc() function.
Case 1: Justifying boxes on a single line ( FIDDLE )
Markup is simple - a bunch of divs with some container element.
CSS looks like this:
div
{
height: 100px;
float: left;
background:pink;
width: 50px;
margin-right: calc((100% - 300px) / 5 - 1px);
}
div:last-child
{
margin-right:0;
}
where -1px to fix an IE9+ calc/rounding bug - see here
Case 2: Justifying boxes on multiple lines ( FIDDLE )
Here, in addition to the calc() function, media queries are necessary.
The basic idea is to set up a media query for each #columns states, where I then use calc() to work out the margin-right on each of the elements (except the ones in the last column).
This sounds like a lot of work, but if you're using LESS or SASS this can be done quite easily
(It can still be done with regular css, but then you'll have to do all the calculations manually, and then if you change your box width - you have to work out everything again)
Below is an example using LESS: (You can copy/paste this code here to play with it, [it's also the code I used to generate the above mentioned fiddle])
#min-margin: 15px;
#div-width: 150px;
#3divs: (#div-width * 3);
#4divs: (#div-width * 4);
#5divs: (#div-width * 5);
#6divs: (#div-width * 6);
#7divs: (#div-width * 7);
#3divs-width: (#3divs + #min-margin * 2);
#4divs-width: (#4divs + #min-margin * 3);
#5divs-width: (#5divs + #min-margin * 4);
#6divs-width: (#6divs + #min-margin * 5);
#7divs-width: (#7divs + #min-margin * 6);
*{margin:0;padding:0;}
.container
{
overflow: auto;
display: block;
min-width: #3divs-width;
}
.container > div
{
margin-bottom: 20px;
width: #div-width;
height: 100px;
background: blue;
float:left;
color: #fff;
text-align: center;
}
#media (max-width: #3divs-width) {
.container > div {
margin-right: #min-margin;
}
.container > div:nth-child(3n) {
margin-right: 0;
}
}
#media (min-width: #3divs-width) and (max-width: #4divs-width) {
.container > div {
margin-right: ~"calc((100% - #{3divs})/2 - 1px)";
}
.container > div:nth-child(3n) {
margin-right: 0;
}
}
#media (min-width: #4divs-width) and (max-width: #5divs-width) {
.container > div {
margin-right: ~"calc((100% - #{4divs})/3 - 1px)";
}
.container > div:nth-child(4n) {
margin-right: 0;
}
}
#media (min-width: #5divs-width) and (max-width: #6divs-width) {
.container > div {
margin-right: ~"calc((100% - #{5divs})/4 - 1px)";
}
.container > div:nth-child(5n) {
margin-right: 0;
}
}
#media (min-width: #6divs-width){
.container > div {
margin-right: ~"calc((100% - #{6divs})/5 - 1px)";
}
.container > div:nth-child(6n) {
margin-right: 0;
}
}
So basically you first need to decide a box-width and a minimum margin that you want between the boxes.
With that, you can work out how much space you need for each state.
Then, use calc() to calcuate the right margin, and nth-child to remove the right margin from the boxes in the final column.
The advantage of this answer over the accepted answer which uses text-align:justify is that when you have more than one row of boxes - the boxes on the final row don't get 'justified' eg: If there are 2 boxes remaining on the final row - I don't want the first box to be on the left and the next one to be on the right - but rather that the boxes follow each other in order.
Regarding browser support: This will work on IE9+,Firefox,Chrome,Safari6.0+ - (see here for more details) However i noticed that on IE9+ there's a bit of a glitch between media query states. [if someone knows how to fix this i'd really like to know :) ] <-- FIXED HERE
Other posts have mentioned flexbox, but if more than one row of items is necessary, flexbox's space-between property fails (see the end of the post)
To date, the only clean solution for this is with the
CSS Grid Layout Module (Codepen demo)
Basically the relevant code necessary boils down to this:
ul {
display: grid; /* (1) */
grid-template-columns: repeat(auto-fit, 120px); /* (2) */
grid-gap: 1rem; /* (3) */
justify-content: space-between; /* (4) */
align-content: flex-start; /* (5) */
}
1) Make the container element a grid container
2) Set the grid with an 'auto' amount of columns - as necessary. This is done for responsive layouts. The width of each column will be 120px. (Note the use of auto-fit (as apposed to auto-fill) which (for a 1-row layout) collapses empty tracks to 0 - allowing the items to expand to take up the remaining space. (check out this demo to see what I'm talking about) ).
3) Set gaps/gutters for the grid rows and columns - here, since want a 'space-between' layout - the gap will actually be a minimum gap because it will grow as necessary.
4) and 5) - Similar to flexbox.
body {
margin: 0;
}
ul {
display: grid;
grid-template-columns: repeat(auto-fit, 120px);
grid-gap: 1rem;
justify-content: space-between;
align-content: flex-start;
/* boring properties: */
list-style: none;
width: 90vw;
height: 90vh;
margin: 2vh auto;
border: 5px solid green;
padding: 0;
overflow: auto;
}
li {
background: tomato;
height: 120px;
}
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
Codepen demo (Resize to see the effect)
Browser Support - Caniuse
Currently supported by Chrome (Blink), Firefox, Safari and Edge! ... with partial support from IE (See this post by Rachel Andrew)
NB:
Flexbox's space-between property works great for one row of items, but when applied to a flex container which wraps it's items - (with flex-wrap: wrap) - fails, because you have no control over the alignment of the last row of items;
the last row will always be justified (usually not what you want)
To demonstrate:
body {
margin: 0;
}
ul {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
align-content: flex-start;
list-style: none;
width: 90vw;
height: 90vh;
margin: 2vh auto;
border: 5px solid green;
padding: 0;
overflow: auto;
}
li {
background: tomato;
width: 110px;
height: 80px;
margin-bottom: 1rem;
}
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
Codepen (Resize to see what i'm talking about)
Further reading on CSS grids:
MDN
Jen Simmons - Learn CSS grid
A Complete Guide to CSS Grid | Codrops CSS Reference
A Complete Guide to Grid - CSS Tricks
This worked for me with 5 images in diferent sizes.
Create a container div
An Unordered list for the images
On css the unordened must be displayed vertically and without bullets
Justify content of container div
This works because of justify-content:space-between, and it's on a list, displayed horizontally.
On CSS
#container {
display: flex;
justify-content: space-between;
}
#container ul li{ display:inline; list-style-type:none;
}
On html
<div id="container">
<ul>
<li><img src="box1.png"><li>
<li><img src="box2.png"><li>
<li><img src="box3.png"><li>
<li><img src="box4.png"><li>
<li><img src="box5.png"><li>
</ul>
</div>
in jQuery you might target the Parent directly.
THIS IS USEFUL IF YOU DO NOT KNOW EXACTLY HOW MANY CHILDREN WILL BE
ADDED DYNAMICALLY or IF YOU JUST CAN'T FIGURE OUT THEIR NUMBER.
var tWidth=0;
$('.children').each(function(i,e){
tWidth += $(e).width();
///Example: If the Children have a padding-left of 10px;..
//You could do instead:
tWidth += ($(e).width()+10);
})
$('#parent').css('width',tWidth);
This will let the parent grow horizontally as the children are beng added.
NOTE: This assumes that the '.children' have a width and Height Set
Hope that Helps.
If you know the number of elements per "row" and the width of the container you can use a selector to add a margin to the elements you need to cause a justified look.
I had rows of three divs I wanted justified so used the:
.tile:nth-child(3n+2) { margin: 0 10px }
this allows the center div in each row to have a margin that forces the 1st and 3rd div to the outside edges of the container
Also great for other things like borders background colors etc