How do I create a row of justified elements with fluid spacing using CSS?
Use the following components:
- A
text-align:justify
container for the row - An
inline-block
container for each column - An
inline-block
placeholder withwidth:100%
to stretch the inside
`
/*Row container is justified*/ #container { width: 100%; text-align: justify; }
/*Column container and placeholder are inline-block*/ object, span { display: inline-block; }
/*Placeholder is stretched to enforce shrink-wrapping*/ span { width: 100%; }
<!--row--> <div id="container"> <!--column--> <object> <!--content--> <div> foo </div> </object> <object> <div> bar </div> </object> <object> <div> baz </div> </object> <object> <div> bop </div> </object> <object> <div> bip </div> </object> <!--placeholder--> <span></span> </div>
Create Center-Justified Menu in Fluid Layout
1) Use text-align: justify;
on your list and center it with margin: 0 auto;
2) Add a pseudo element to stretch the items to max width
FIDDLE (I added a border to visualize the efect)
.wpr { border-top: 2px solid #111; border-bottom: 2px solid #111;}ul { text-align: justify; min-width: 500px; width: 80%; display: block; margin: 0 auto; border: 1px solid tomato;}ul:after { content: ''; display: inline-block; width: 100%;}li { display: inline-block; padding-top: 16px; box-sizing: border-box;}
<div class="wpr"> <ul> <li><a href="#">VISIT</a> </li> <li><a href="#">EVENTS</a> </li> <li><a href="#">EXHIBITIONS</a> </li> <li><a href="#">COLLECTIONS</a> </li> <li><a href="#">LEARN</a> </li> </ul></div>
Fluid width with equally spaced DIVs
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
fixesinline-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>
Better way to set distance between flexbox items
- Flexbox doesn't have collapsing margins.
- Flexbox doesn't have anything akin to
border-spacing
for tables (edit: CSS propertygap
fulfills this role in newer browsers, Can I use)
Therefore achieving what you are asking for is a bit more difficult.
In my experience, the "cleanest" way that doesn't use :first-child
/:last-child
and works without any modification on flex-wrap:wrap
is to set padding:5px
on the container and margin:5px
on the children. That will produce a 10px
gap between each child and between each child and their parent.
Demo
.upper {
margin: 30px;
display: flex;
flex-direction: row;
width: 300px;
height: 80px;
border: 1px red solid;
padding: 5px; /* this */
}
.upper > div {
flex: 1 1 auto;
border: 1px red solid;
text-align: center;
margin: 5px; /* and that, will result in a 10px gap */
}
.upper.mc /* multicol test */ {
flex-direction: column;
flex-wrap: wrap;
width: 200px;
height: 200px;
}
<div class="upper">
<div>aaa<br/>aaa</div>
<div>aaa</div>
<div>aaa<br/>aaa</div>
<div>aaa<br/>aaa<br/>aaa</div>
<div>aaa</div>
<div>aaa</div>
</div>
<div class="upper mc">
<div>aaa<br/>aaa</div>
<div>aaa</div>
<div>aaa<br/>aaa</div>
<div>aaa<br/>aaa<br/>aaa</div>
<div>aaa</div>
<div>aaa</div>
</div>
Fluid navigation items of different widths with equidistant spacing
I thought about this for a while and came up with two reasonable approaches, both of which are pretty good but not exactly pixel perfect. One is CSS based only and the second is aided by jQuery (JavaScript).
CSS Approach - pretty good approximation
Consider the following HTML:
<ul class="nav ex1">
<li class="first"><a href="#">Home</a></li>
<li><a href="#">Collections</a></li>
<li class="tight"><a href="#">About Us</a></li>
<li><a href="#">Slocklists</a></li>
<li class="tight"><a href="#">Trade Enquiries</a></li>
<li><a href="#">Press</a></li>
<li class="last"><a href="#">Contact Us</a></li>
</ul>
I added some classes as hooks for the styling.
The CSS is as follows:
.nav.ex1 {
outline: 1px dashed blue;
width: 100%;
margin: 0;
padding: 0;
display: table;
}
.nav.ex1 li {
display: table-cell;
outline: 1px dotted gray;
width: 20%;
white-space: pre;
text-align: center;
}
.nav.ex1 li.first {
width: 1%;
}
.nav.ex1 li.last {
width: 1%;
}
.nav.ex1 li.tight {
width: 1%;
}
In Example 1, the ul.nav
parent container uses display: table
and width: 100%
. The child li
elements are table-cell
's. I added white-space: pre
to prevent some of the links from wrapping into two lines, and text-align: center
to keep the text centered.
The trick is to force some of the table-cell's to shrink-to-fit the text, and you can do this by setting width: 1%
which is non-zero but too small to hold the text (unless your screen is 10,000 pixels wide). I shrink-to-fit the first and last cells which forces them to align to the left and right edges of the parent container. I then force every other table-cell to shrink-to-fit by added the .tight
class.
The remaining table's cells will have a width of 20% which will keep them evenly spaced between their two nearest neighbors. HOWEVER, there will be some slight variation in spacing among the links in the row, which is why I call it an approximation.
jQuery Aided Solution
In Example 2, the markup is essentially the same and the CSS is:
.nav.ex2 {
outline: 1px dashed blue;;
margin: 0;
padding: 0;
display: block;
overflow: auto;
width: 100%;
}
.nav.ex2 li {
float: left;
display: block;
outline: 1px dotted gray;
width: auto;
}
In this case, the li
elements are floated left and I use width: auto
.
The trick is to calculate the magic left-margin value and apply it to all the li
elements except for the first one.
The jQuery action is:
$(window).resize(function () {
navResizer();
});
// On load, initially, make sure to set the size.
navResizer();
function navResizer() {
var $li_w = 0;
var $ul_w = $(".nav.ex2").innerWidth();
$( ".nav.ex2 li" ).each(function( index ) {
$li_w += $(this).innerWidth();
});
var li_margin = Math.floor(($ul_w-$li_w)/6);
$(".nav.ex2 li").not(".first").css("margin-left",li_margin);
$("p.note").text( "Widths: ul.nav: " + $ul_w + " all li: " + $li_w + " Left margin: " + li_margin);
}
Basically, the action calculates the width of ul.nav
($ul_w
), and the total widths of all the li
child elements ($li_w
).
The left-margin is calculated by ($ul_w - $li_w)/6
where 6 is the number of gaps between the 7 links.
The key line of code is: $(".nav.ex2 li").not(".first").css("margin-left",li_margin);
I use .not(".first")
to omit the first li
element and then .css
to set the left margin.
The one slight defect is at the far right where the link is not quite right justified, but you can fix that by floating the last li
to the right.
For the most part, if your link texts were similar in length, you would be hard pressed to distinguish the two. Both approaches are not quite pixel perfect, but pretty good.
Fiddle: http://jsfiddle.net/audetwebdesign/xhSfs/
Footnote
I tried some other approaches using text-align: justify
and inline-block
, but the CSS engine does not treat inline-blocks like regular words, so will not justify a line of inline-blocks.
Setting left-margin
to a % value will not quite work at some window widths and the right-most link will not be on the edge as desired.
The jQuery approach has been tried before, see:
Evenly-spaced navigation links that take up entire width of ul in CSS3
Fluid width with equally spaced DIVs + last row left aligned
Ok, here's the damn easy solution with css:
Simply add so many divs of how many in a row would be (in this case 4) and give them a height of 1px.
Nothing to see and all works like charm without javascript.
Here's the new fiddle: http://jsfiddle.net/L2mPf/1/
Thanks to @GGG for focusing me back on css and this solution.
How do I remove spacing around elements inside .container-fluid?
Change the class name .container-fluid
to something else as that is a bootstrap predefined class.
You can change the class name to anything else you want.
Codepen: https://codepen.io/manaskhandelwal1/pen/mdrzqOM
Vertically centered text, in 8 item justified, fluid width menu in 2 rows and gutters
For such a structure I would use a table, way more handy:
HTML
<table id="wrapper">
<tbody >
<tr>
<td><a href="#">Normal text</a></td>
<td><a href="#">Normal text</a></td>
<td><a href="#">Normal text</a></td>
<td><a href="#">Normal text</a></td>
</tr>
<tr>
<td><a href="#">longer text longer text longer text</a></td>
<td><a href="#">Normal text</a></td>
<td><a href="#">Normal text</a></td>
<td><a href="#">Normal text</a></td>
</tr>
</tbody>
</table>
CSS
#wrapper {
col {
max-width: 250px;
}
background: grey;
border-spacing:0;
border-collapse:collapse;
}
tbody {
text-align: justify;
-ms-text-justify: distribute-all-lines;
text-justify: distribute-all-lines;
padding: 0;
margin: 0;
font-size: 0.1px;
}
td {
width: 25%;
height: 100px;
vertical-align: middle;
background-color: #ddd;
font-size: 22px;
color: #000000;
margin-bottom: 1%;
text-align: center;
border: 1px solid black;
}
li a {
text-decoration: none;
}
Fiddle
Managing justify-content: space-between on last row
Use an invisible pseudo-element that occupies the last slot in the container:
.main::after {
height: 0;
width: 30%;
content: "";
}
The height is 0 so that when rows are filled, and the pseudo-element starts the next line, it doesn't add height to the container.
Full code:
.main { background: #999; margin: 0 auto; width: 500px; display: flex; flex-wrap: wrap; justify-content: space-between;}.box { background: #7ab9d7; color: #555; height: 30px; width: 30%; margin-bottom: 30px; text-align: center; font-size: 30px; padding-top: 120px;}.main::after { height: 0; width: 30%; content: "";}
<div class="main"> <div class="box">1</div> <div class="box">2</div> <div class="box">3</div> <div class="box">4</div> <div class="box">5</div></div>
Related Topics
Position:Fixed in Windows Phone 7
What Is CSS "[Class*=My-Class] .My-Subclass" Doing
How to Set a Javafx Static Property in CSS
Image Downscaling with CSS … Images Are Blurry in Several Browsers
3D-Like Hover Effect on Button
Characters from Embedded Google Fonts Not Showing Up in Firefox 4 and Ie9
Unwanted Bolding Added to Font in Browsers
Bootstrap 3 Full Width Image and Div in Container
Why Does Chrome Read The Svg Circle Radius from The Style Attribute
Only CSS Rotate Box-Shadow Without Original Element
CSS Media Queries Not Working in Safari
How to Automatically Add Browser Prefix to CSS3 Properties
How to Add Multiple Browser Specific Values into a CSS Style in React
CSS: How to Center Box Div Element Directly in Center
Use Full Width Excluding Overflow Scrollbar with "Position: Absolute"
Create a Loop Using SCSS to Change Background Images with CSS3 Animate