How to get tiles centered and left-justified at the same time - html

I have a container of tiles (or divs) and I want the container to be centered, while the tiles are left justified in the container.
so if the window is small:
..[s][s][s]..
..[s][s].....
If the window is widened a little:
...[s][s][s]...
...[s][s]......
further:
.[s][s][s][s].
.[s]..........
I've tried:
#container's-parent: { display: block; text-align: center; }
#parent: { display: inline-block; text-align: left; }
.tiles: { display: inline-block }
but that doesn't appear to work.
I want this to work in Chrome at least, but I also need to eventually support latest FF, Safari, and IE 10+

FWIW: It's now 2017 and the grid layout module does this out of the box (codepen demo). If the browser support suits you - then use grid. If not, then read on....
As mentioned in #Skadi2k3's answer, the best you can do with CSS is with a series of media queries.
That being said, if you are using a preprocessor such as LESS - this isn't such a difficult or error-prone task. (although, yes, the CSS will still be long and ugly)
FIDDLE or CODEPEN (Supports LESS)
Here's how to take advantage of LESS to set up the media queries:
Set up an iteration mixin like this: (You can paste this code into http://less2css.org)
#item-width:100px;
#item-height:100px;
#margin: 5px;
#min-cols:2;
#max-cols:12; //set an upper limit of how may columns you want to write the media queries for
.loopingClass (#index-width) when (#index-width <= #item-width * #max-cols) {
#media (min-width:#index-width) {
#content{
width: #index-width;
}
}
.loopingClass(#index-width + #item-width);
}
.loopingClass (#item-width * #min-cols);
The above mixin will spit out a series of media queries in the form:
#media (min-width: 200px) {
#content {
width: 200px;
}
}
#media (min-width: 300px) {
#content {
width: 300px;
}
}
#media (min-width: 400px) {
#content {
width: 400px;
}
}
...
#media (min-width: 1200px) {
#content {
width: 1200px;
}
}
So with a simple markup like:
<ul id="content">
<li class="box"></li>
<li class="box"></li>
...
<li class="box"></li>
</ul>
With remaining CSS (LESS):
#content {
margin:0 auto;
overflow: auto;
min-width: #min-cols * #item-width;
max-width: #max-cols * #item-width;
display: block;
list-style:none;
background: aqua;
}
.box {
float: left;
height: #item-height - 2 *#margin;
width: #item-width - 2*#margin;
margin:#margin;
background-color:blue;
}
... you get the desired result.
...and it's super easy to customize the layout:
All I need to do is change the variables that I used in the LESS mixin according to my needs - I get the exact layout that I'm after.
So let's say I have items 300px X 100px with a minimum of 2 columns and max 6 columns and a margin of 15px - I just modify the variables like so:
#item-width:300px;
#item-height:100px;
#margin: 15px;
#min-cols:2;
#max-cols:6;
...and voila, I get this CODEPEN

What about this?
http://jsfiddle.net/cHTVd/1/
You have to set display: inline-block for the container too:
body { text-align: center; }
#container {
width: 250px;
border: solid green 3px;
display: inline-block;
text-align: left;
}
.tile { width: 100px;
border: solid red 3px;
display: inline-block;
margin: 8px;
}
EDIT: Giving container relative width is easy - http://jsfiddle.net/cHTVd/3/
I am afraid that "reverse justify" would have to be done with JS. CSS text-align has only four values: left | right | center | justify. It's trivial to change it to justify - http://jsfiddle.net/cHTVd/4/. For the "reverse justify" you would probably need some javascript work similar to this: http://jsfiddle.net/yjcr7/2/.

Unless you want to use Javascript you could use the media query (lots of them):
#parent{ width: 100px; margin: 0 auto;padding:0;}
.tile{width: 80px; float:left;padding:10px;outline:2px dashed red;}
#media screen and (max-width:200px)
#media screen and (min-width:201px) and (max-width:300px){
#parent{ width: 200px;}
}
#media screen and (min-width:301px) and (max-width:400px){
#parent{ width: 300px;}
}
#media screen and (min-width:401px){
#parent{ width: 400px;}
}
The problem is that you need to know how many of the tiles fit into the container to set a tight fitting width to the container, but that is a bottom up information and not how cascading works. If you want a more elegant solution you need to use JS on resize events, calculate how many boxes fit into one line and set the width of the container.

I solved this on my own projects in a quick and dirty manner by simply adding several empty "tiles" to the end that are the same width as the regular content tiles, but with a negligible height. These empty tiles serve to "push" the content tiles on the last line to the left where they belong. (The "real" last line often consists of nothing but empty tiles that are invisible to the user.) So, for example, if there some number of tiles on a page, and I expect the width of the browser to be able to accommodate from 1 to 4 (for example) tiles in width, I will add 3 extra empty tiles (designated "e") to the end:
..[s][s][s]..
..[s][s][e]..
...[e][e].... // this row isn't visible because [e] has no content
If the window is widened a little:
...[s][s][s]...
...[s][s][e]...
....[e][e].....
further:
.[s][s][s][s].
.[s][e][e][e].
or more narrow:
.[s][s].
.[s][s].
.[s][e].
.[e][e].
or really narrow
..[s]..
..[s]..
..[s]..
..[s]..
..[s]..
..[e]..
..[e]..
..[e]..
The empty tiles may pile up at the bottom, but since they are some small height, they don't create a whole lot of extra whitespace.
A hackish solution for sure, but it does work, is reliable on different browsers, and doesn't require a mound of code.

Answer the same like Danield's, but in SCSS:
*
{
margin:0;padding:0;
}
$item-width:200px;
$item-height:100px;
$margin: 15px;
$min-cols:2;
$max-cols:6; //set an upper limit of how may columns you want
//to write the media queries forss to css
#for $i from $min-cols to $max-cols + 1 {
$index-width: $i*$item-width;
#media (min-width:$index-width) {
#content {
width: $index-width;
}
}
}
#content {
margin:0 auto;
overflow: auto;
min-width: $min-cols * $item-width;
max-width: $max-cols * $item-width;
display: block;
list-style:none;
background: aqua;
}
.box {
float: left;
height: $item-height - 2 *$margin;
width: $item-width - 2*$margin;
margin:$margin;
background-color:blue;
}
It generates the same CSS like his solution.
Working codepen example here.

Try this:
.tiles: {
display: inline-block;
margin: 0 auto;
max-width: 90%;
}
No verticall margin, auto margin for horizontal sides!

This is pretty easy with flexbox.
.container {
display: flex;
flex-wrap: wrap;
}
You can customize how the tiles fit as well, such as giving them a starting point (flex-basis) or how much the tile can grow or shrink
.tile {
flex-grow: 0;
flex-shrink: 0;
flex-basis: 3em;
Check out the codepen: http://codepen.io/anon/pen/uexbf

Looks like there is solution (though it is described in Russian and I haven't found a translation).
Demo can be seen here.

No idea how to do it with CSS, if it's even possible. But with jQuery it's rather simple:
$('button').click(function(){
$('nav ul').each(function(){
$parent = $(this).parent();
$parent.width( $(this).width() );
});
});
nav {
display: inline-block;
text-align: left; /* doesn't do anything, unlike some might guess */
}
ul {
display: inline;
}
/* needed style */
ul {
padding: 0;
}
body {
width: 420px;
}
/* just style */
body {
background: #ddd;
margin: 1em auto;
}
button {
display: block;
}
nav {
background: #bbb;
margin: 1rem auto;
padding: 0.5rem;
}
li {
display: inline-block;
width: 40px;
height: 20px;
border: solid thin #777;
margin: 4px;
background: #999;
text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>fix</button>
<nav>
<ul>
<li>3</li>
<li>.</li>
<li>1</li>
<li>4</li>
</ul>
</nav>
<nav>
<ul>
<li>3</li>
<li>.</li>
<li>1</li>
<li>4</li>
<li>1</li>
<li>5</li>
<li>9</li>
<li>2</li>
<li>6</li>
<li>5</li>
<li>3</li>
<li>5</li>
</ul>
</nav>

Related

How can I create three responsive divs using display: table and no JS?

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.

Nav bar with diving image

I'm really struggling to get this navigation-menu with a image that splits the navigation to work. Responsive is a big plus. I don not believe the current code is on the the right way to go, so please be open minded of how to approach this problem.
HTML
<div id="nav">
<ul class="nav-left">
<li>1</li>
<li>2</li>
</ul>
<div class="nav-logo"></div>
<ul class="nav-right">
<li>3</li>
<li>4</li>
</ul>
</div>
CSS
#nav {
width: 400px;
background: #f5f5f5;
border: 1px solid grey;
text-align: center;
}
.nav-left, .nav-right, .nav-logo {
display: inline-block;
height: 30px;
vertical-align:bottom;
}
.nav-left {
background: red;
}
.nav-right {
background: red;
}
.nav-right, .nav-left {
width: 100px;
line-height: 30px;
padding: 0;
}
.nav-logo {
background: yellow;
width: 30px;
height: 100px;
margin-left: 10px;
margin-right: 10px;
}
ul {
margin: 0;
text-align: justify;
list-style: none;
}
li {
display: inline;
width: 100%;
}
Update 05.05.14
Updated it with my current code as requested.
I have gone ahead and made a slightly responsive header for you: JSfiddle (Note: random coffeeshop logo borrowed from google image search... man I should go get a coffee)
The idea is to use the html5 nav element to contain your links, each with a width:20% so it resizes with the width of the screen.
The image is positioned with background:url('...') no=repeat center; to avoid sizing problems. It's in a separate div to allow you to stripe the <nav> element. This is possible with pure css.
As you want to position the links vertically they are nested in divs, and space for the image is made using an empty div with the same width:20%; property as the link containers.
The design breaks once you get close to small mobile device widths (as the links cover the image). For this you can use #media queries.
I hope this gives you a starting point, but design is very subjective and there are many different ways to do it.
It may be worth while to style your page with Bootstrap and inspect their CSS to see what's happening.
Can you please add your css and html codes into your qustion then I can help you with a best solution. Also if you want then email me your codes, I will send you the best solution.
Orherwise just add a class .navfix on the main navigation container div or ul. then add the style property z-index:9999999 for the class .navfix into your stylesheet. Also if you have use any other div for the background then you have to add same thing for the nav background container but here z-index property should be negative or lower then other one.
sample :
.navfix {
z-index:9999999;
}
for background container (if you have)
then
.navfix {
z-index:9999999;
}
.backgrounContainerClassName {
z-index:-1;
}

How to fix max-width and float:left interaction

http://jsfiddle.net/Rncu6/
The green div has a max-width attribute, and it should shrink when the screen shrinks.
Instead, what happens is that the green div falls off to another line. If I try to remove the float:left on the green div, it suddenly overlaps with the yellow div, which is not what I want.
How do I fix this?
This seems like a really frustrating issue. The best way I can think to solve it is to remove float:left from p and replace it with display: table-cell.
p {
display: table-cell; /* replaces float:left */
max-width: 300px;
background-color: lightgreen;
height: 200px;
}
The only problem with this approach is that it will render all the margin attributes useless. To work around that, you can just add the inverse of those margin attributes to #img1. For example:
p { margin-left: 10px; }
Would be replaced with:
#img1 { margin-right: 10px; }
JS Fiddle Example
Caveat: I don't know how small you want your minimum width to become, but you'll notice that at a certain point the p will still move onto the next line. This is because it is becoming too small for individual words (e.g. longer words like "paragraph") to fit on one line. To work around that, you can use the word-break:break-all; attribute.
p { word-break: break-all }
That way, the width of p will continue to shrink until the width can no longer fit individual characters on one line.
JS Fiddle Example
Give width in percentages
#img1 {
background-color: yellow;
width: 20%;
height: 100px;
float: left;
}
p {
float:left;
margin-top: 0;
max-width: 50%;
background-color: lightgreen;
margin-left: 10px;
height: 200px;
}
http://jsfiddle.net/Rncu6/11/
The overlapping occurs because the size of the DOM is becomes larger than the browser so it gets pushed below the img div. As already mentioned you can use % to compensate for that. Although, if you want to absolutely define the divs in pixels until the browser can't display them any more.
To expand upon the current answer you could use Media queries...
#img1 {
background-color: yellow;
width: 100px;
height: 100px;
float: left;
}
p {
margin-top: 0;
float: left;
max-width: 300px;
background-color: lightgreen;
margin-left: 10px;
height: 200px;
}
p:after {
content: " ";
display: block;
height: 0;
clear: both;
}
#media screen and (max-width: 450px) {
#img1 {
width: 20%;
}
p {
max-width: 50%;
}
}
And here's the jsfiddle - http://jsfiddle.net/SxLCJ/

Center float container without width

I have this HTML:
<div id="container">
<article></article>
<article></article>
<article></article>
<article></article>
<article></article>
</div>
and this CSS:
#container {
overflow: hidden
}
article {
float:left;
height: 200px;
width: 200px;
background-color: red;
margin: 5px;
}
​
​I want to center the #container without specifying a width. Is it possible?
Here is the Fiddle.
Edit:
I need the width of the #container to change to fit the articles. If the body is 450px width then there will be two articles per row, so the width of the container should be 400px aprox. If the body is 1100px width then ther will be five articles per row, so the width of the container should be 1000px aprox.
You could try something like this (jsfiddle):
HTML:
<html>
<body>
<div id="container">
<article></article>
<article></article>
<article></article>
<article></article>
<article></article>
</div>
</body>
</html>​
CSS:
html, body { margin: 0; padding: 0; }
body { text-align: center; }
#container {
overflow: hidden;
margin: 0 auto;
width: 90%;
text-align: left;
}
article {
display:inline-block;
height: 200px;
width: 200px;
background-color: red;
margin: 5px;
}
​
update 2015
I noticed there was a slight issue with the previous set-up. In that keeping the articles within the first placeholder doubled up the margins. This led to slight inconsistencies when resizing the page across each article wrap point.
This updated fiddle gets rid of those issues:
http://jsfiddle.net/C4fbX/4/
However, this kind of layout could very likely be achieved in a nicer way with Flexbox these days.
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
answered 2012
The following method works, however it is a little mad. It's rather annoying that this isn't something that CSS can handle easily:
fiddle
http://jsfiddle.net/C4fbX/
method
This method works on the basic idea posted by Nick, and uses this method to then position a left floating system... which fixes the problem where you always end up with center aligned elements within the centered container.
So instead of:
[][][][]
[][]
You get:
[][][][]
[][]
The following stipulations are required:
You need to include as many placeholder elements as you have articles. The method uses these to calculate where to indent the articles from. This also means that the width and horizontal margin/padding of the placeholder elements has to match that of the articles.
The articles need to be placed within the first placeholder.
In order to get around the whitespace issue with regard to inline-block, the font-size and line-height are zeroed out, which means they have to be manually set again for the articles. You can get around this by removing these zeroed attributes from the css and just making sure your placeholder markup doesn't have any whitespace.
I very much doubt this will work in older browsers - but seems to in the current modern ones.
Relying on position absolute means that your articles wont take up their usual space in the document, so you'd have to account for this in your design or set a fixed height on your #container element
mark up
<div class="container">
<div class="placeholder">
<div class="position">
<article>a</article>
<article>b</article>
<article>c</article>
<article>d</article>
<article>e</article>
</div>
</div>
<div class="placeholder"></div>
<div class="placeholder"></div>
<div class="placeholder"></div>
<div class="placeholder"></div>
</div>
css
.container {
font-size: 0;
line-height: 0;
text-align: center;
}
.placeholder {
display: inline-block;
width: 200px;
margin-left: 5px;
margin-right: 5px;
height: 0px;
}
.position {
position: absolute;
}
article {
font-size: 12pt;
line-height: 1.2em;
float: left;
margin: 5px;
width: 200px;
height: 100px;
background: red;
}
Do you mean centre the articles within the container, whilst allowing them still to wrap? In which case (jsfiddle):
#container {
text-align: center;
}
article {
display:inline-block;
height: 200px;
width: 200px;
background-color: red;
margin: 5px;
}
​
After considering several options, I found that using media queries is the simpler way to do it.
In this case it will be something like this:
#media (max-width: 420px) {
#container {
width: 210px;
}
}
#media (min-width: 420px) and (max-width: 630px) {
#container {
width: 420px;
}
}
#media (min-width: 630px){
#container {
width: 630px;
}
}
Here is the fiddle.
Take out float: left; and add margin:auto;

Fluid width with equally spaced DIVs

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