Don't use % for that layout...
- Mon 71° 47°
- Tue 70° 48°
- Wed 80° 49°
Dust off your HTML and CSS, and think for a second how you would implement the “weather forecast” card above.
The first things you’ll notice, is that the horizontal real estate needs to be evenly distributed between a number
of elements (three in this case). The naive approach would be to divide the available space by three, hard-code the
width of each inlined element, and call it day. But we know better, and are well aware of the vast diversity of screen dimensions,
we could also think of using an all mighty display: inline-block
while throwing in some widths using percentage digits.
But is it good enough?
Products change, new features come and others go, new trends trigger redesigns, products will be translated into other verbose languages, and let's not don’t forget about A/B testing. This is why the fewer constraints we set in a layout, the easier will be to adopt changes and variations.
Case Study
We are going to walk through a few different approaches that will make your and your colleague's future life easier
when working with these kinds of layouts and we will start by simplifying the concepts by only using bare <span>
elements, however, the principles will stand for more complex structures with any number of children elements.
Our solution must satisfy the following requirements:
- The elements should be distributed evenly across the available space.
- It should handle a variable number of elements.
- It should handle variable width for each element.
We will take 4 approaches, sorted descending on browser compatibility:
- Using a table
- Using display table
- Using Justify
- Using flex box
The <table> element
Even though some people could laugh at the thought of using <table>
elements in these days, if absolute cross-browser compatibility is a requirement, this is the way to go.
1 | 2 | 3 |
1 | 222 | 3 |
1 | 2 | 3 | 4 |
1 | 2 | 3 | 4 |
table {
text-align: center;
width: 100%;
}
<table>
<tbody>
<tr>
<td>
<span>1</span>
</td>
<td>
<span>2</span>
</td>
<td>
<span>3</span>
</td>
<td>
<span>4</span>
</td>
</tr>
</tbody>
</table>
Display: table
With this approach, we get the benefits of a <table>
without the performance hit.
div {
display: table;
width: 100%;
}
span {
display: table-cell;
}
<div>
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
</div>
Text-align: justify
The devil is on the details, compare the alignment with the previous examples, you will note as the name implies that with this approach we can 'justify' the content so it starts and ends at the edges of the container element, as well as how it wraps to the next line when the width is overflown by the content.
The way this is achieved is by inserting a pseudo element after the container element forcing the container to reach a full width hence spacing the elements edge to edge.
span {
display: inline-block
}
div {
text-align: justify;
width: 100%;
}
div::after {
content: '';
display: inline-block;
width: 100%;
}
/* -- Internet Explorer support -- */
div:after {
content: '';
display: inline-block;
width: 100%;
}
<div>
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
</div>
Display: flex
The easiest way to work with complex layouts is definitely the flex-box, the draw back is the browser support. Depending on the actual objective we use two alternatives to justify: space-around or space-between.
space-around
space-between
/* Space Around */
div {
display: flex;
justify-content: space-around;
width: 100%;
}
/* Space Between */
div {
display: flex;
justify-content: space-between;
width: 100%;
}
<div>
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
</div>
Conclusion
For the initial example, in my opinion display: table
is the way to go, here is why:
- If the number of elements change the task is as simple as adding or removing a list element, no CSS changes are required whatsoever.
- If the width of the images change the layout will not be affected.
- If the container gets too small the elements will not overlap with each other maintaining readability.
- Browser support is high enough to render the intended design without adding overhead to the compliant browsers.
- Mon 71° 47°
- Tue 70° 48°
- Wed 80° 49°
ul {
border: 9px solid #333;
border-radius: 20px;
display: table;
margin: auto;
padding: 14px 0;
width: 85%;
}
li {
display: table-cell;
text-align: center;
}
img {
display: block;
margin: auto;
}
span{
display: inline-block;
padding: 0 4px;
}
<ul>
<li>
<span>Mon</span>
<img src="/svgs/storms.svg"
width="60" height="60"
alt="storms"/>
<span>71°</span>
<span>47°</span>
</li>
<li>
<span>Tue</span>
<img src="/svgs/rain.svg"
width="60" height="60"
alt="rain"/>
<span>70°</span>
<span>48°</span>
</li>
<li>
<span>Wed</span>
<img src="/svgs/clear.svg"
width="60" height="60"
alt="clear"/>
<span>80°</span>
<span>49°</span>
</li>
</ul>