Front-end goodies
Front-end goodies
Krasimir Tsonev
Buy on Leanpub

Introduction

If you (like me) building web applications you probably deal with a lot of CSS, HTML or JavaScript code. We had to fight with all the cross-browser specific issues and find the best solution for our project. Every time when I solve a problem I feel that I have to document it somewhere. My blog is such a place. It contains many articles based on problems that I faced up with in my daily job. I always had an idea to write a book with all these materials and finally I have enough free time to do it.

caption

caption

CSS Challenge - expand and center an image

That’s first of (I hope) many posts with such an idea. Problems solved with pure CSS. No JavaScript. I’m working on a gallery type site and I need to show photos. Of course the size of the images is unknown.[STOP]

The following sketch illustrates the situation:

CSS challenge

CSS challenge

I.e. I have a div, wrapper which contains an image tag. The picture should expand and fill the parent element. Together with that it should be centered vertically/horizontally. The size of the image and the container could vary.

1 <div class="wrapper">
2 	<img src="pic.jpg" />
3 </div>

Let’s say that the wrapper has the following CSS applied:

1 .wrapper {
2          width: 400px;
3          height: 200px;
4          overflow: hidden;
5     }

As I said, the dimensions of the container could vary. The solution should work even with 400x200. And remember, I can’t use JavaScript to get the size of the image, make calculations or change CSS properties.

What I tried and it didn’t work

The very first thing, which I did was to apply max-width: 100% to the image tag. The photo was successfully resized to exactly 400px by width. The problem was that it wasn’t centered and, more importantly if the image was small and its width was less then 400px there was some unfilled space. So, I replaced max-width with simply width. This guaranteed that the image will be resized to exactly 400px no matter what. The first step was made and I thought that I was in the right direction.

The next thing, which I had to fight with was the centering. I tried several variants with negative margin or padding. The absolution positioning or the usage of percentages didn’t help. It looked that it is not possible to cover all the cases without to use JavaScript.

Even if the above problem is solved that will be only 50% of the job, because if the width of the wrapper is less then its height everything starts from the beginning. So, I wasn’t able to figure out how to make the things in the CSS styling. I had to change the markup and try again.

The solution

During the development of krasimirtsonev.com I used background-size: cover. What it does is to resize your background image like that so it fills all the available space. So, the first thing which I did is to set the image as a background of the wrapper.

1 <div class="wrapper" style="background-image: url('pic1.jpg');"></div>

Yes, I know that inline styling is not a good idea. Also the missing of img tag means that search engines will not parse very well my images. Anyway, the type of the project allows those sacrifices.

After that I added background-size: cover to the wrapper’s styles:

1 .wrapper {
2     width: 400px;
3         height: 200px;
4         overflow: hidden;
5         background-size: cover;
6 }

Only this property solves half of the problem. After that resizing the image matched my criterias.

Another useful property is background-position. I added background-position: center center and voila - mission completed.

<iframe width="100%" height="400" src="http://jsfiddle.net/krasimir/W7GuL/3/embedded/result,css,html/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>

CSS Challenge - Layouting

The first challenge, was something which I was thinking a lot these days. The next one is actually a well known common task, but it is still difficult. In every project we have different types of layouts. Of course there are some patterns. The idea today is to implement them with pure CSS.

Layout A - everything centered

caption

caption

That’s maybe the most simplest layout. Usually the markup is something like that:

1 <div class="layout-a">
2     <img src="..." />
3     <p>...</p>
4 </div>

As you know, if you have container with elements which are inline objects, you could use text-align: center to position them in the middle. If you apply this to our wrapper the image will be centered, because it is by default an inline element. Also the text in the paragraph will be centered, because the <p> tag inherits the text-align from its parent. However our layout is a bit different. First of all the image and the paragraph should be with equal widths. The text should be left aligned and will be nice if we could apply the same CSS with different widths of the container.

Let’s imagine that we don’t know the width of the image. This means that we can’t also set the width of the paragraph. So, we should simply rely on the parent element. By default the <p> tag is a block element so its width is 100%. If we apply the same value to the <img /> tag they will be with equals widths.

Because we know the wrapper’s width we could use margin: 0 auto to position it in the center. At the end we should apply text-align: left to the paragraph so its text sticks to the left. The final CSS of the layout is:

 1 .layout-a {
 2     width: 360px;
 3     margin: 0 auto;
 4     text-align: center;
 5 }
 6 .layout-a img {
 7     width: 100%;
 8 }
 9 .layout-a p {
10     text-align: left;
11 }

Layout B - an image and text

caption

caption

The requirements here are similar. We know only the width of the container and we should position the image on the left and the text on the right. Also the picture should expand if the wrapper has bigger width.

We should use floats here. We could apply float: left to the image, but in this case the text will go around the picture. What we want to achieve is to keep the area below the image free. Something like this:

caption

caption

To fix this problem we have to apply 50% width to both, the image and the paragraph. This will make two columns. And if we float them to left we are almost done.

1 .layout-b img {
2     width: 50%;
3     float: left;
4 }
5 .layout-b p {
6     width: 50%;
7     float: left;
8 }

We used floats, but we should clear them, because this will break the layout. Instead of adding more markup we may use :after pseudo class. The final CSS looks like that:

 1 .layout-b {
 2     width: 360px;
 3     margin: 0 auto;
 4 }
 5 .layout-b:after {
 6     content: "";
 7     display: block;
 8     clear: both;
 9 }
10 .layout-b img {
11     width: 50%;
12     float: left;
13 }
14 .layout-b p {
15     width: 50%;
16     float: left;
17     margin: 0;
18     padding: 0 0 0 10px;
19     -webkit-box-sizing: border-box;
20 	-moz-box-sizing: border-box;
21 	box-sizing: border-box;
22 }

Notice that I used a little padding in the paragraph styling. Because of that I needed to apply box-sizing: border-box. Otherwise those 10px will move the text below the image.

If you want to have the text on the left and the image on the right then you could just switch the places of the tags in the container. Also you should update the padding of the paragraph, so its padding-right property contains 10px.

caption

caption

Of course instead of text you could use another image. They both will take exactly 50% of the wrapper.

caption

caption

Layout C - a bit complex

caption

caption

Two images and little text. It’s almost like the previous layout, but we need more markup.

1 <div class="layout-c">
2     <img src="..." />
3     <div class="layout-c-right">
4         <img src="..." />
5         <p>...</p>
6     </div>
7 </div>

As you may guess, we still have two columns, but this time there is a conflict. If we apply width: 50%; float: left; to the <img /> tag it will be valid for the image inside the nested container .layout-c-right. That’s why we should overwrite this style and the layout’s CSS transforms to:

 1 .layout-c {
 2     width: 360px;
 3     margin: 0 auto;
 4 }
 5 .layout-c:after {
 6     content: "";
 7     display: block;
 8     clear: both;
 9 }
10 .layout-c img {
11     width: 50%;
12     float: left;
13 }
14 .layout-c-right {
15     float: left;
16     width: 50%;
17 }
18 .layout-c-right img {
19     width: 100%;
20     float: none;
21 }
22 .layout-c p {
23     margin: 0;
24     padding: 5px 0 0 10px;
25     -webkit-box-sizing: border-box;
26 	-moz-box-sizing: border-box;
27 	box-sizing: border-box;
28 }

Same like in layout B, if you want to switch the positions of the columns you just have to change their order in the DOM. And of course update the padding of the paragraph.

caption

caption

Layout D - many columns and space between them

caption

caption

It’s not that simple as it looks like. Of course, we will use floats, so we should keep the clearing. In our case we have three columns, so every of them have to take exactly 33.33% of the whole width. The markup that we are using is:

 1 <div class="layout-d">
 2     <div class="layout-d-column">
 3         <img src="..." />
 4         <p>...</p>
 5     </div>
 6     <div class="layout-d-column">
 7         <img src="..." />
 8         <p>...</p>
 9     </div>
10     <div class="layout-d-column">
11         <img src="..." />
12         <p>...</p>
13     </div>
14 </div>

There should be some space between the columns. By using padding and box-sizing we could achieve this:

1 .layout-d-column {
2     width: 33.33%;
3     float: left;
4     padding: 0 20px 0 0;
5     -webkit-box-sizing: border-box;
6     -moz-box-sizing: border-box;
7     box-sizing: border-box;
8 }

If you try the things so far you will notice that the third column is not positioned to the very right side of the wrapper. That’s because those 20px padding. Hopefully there is a way to fix that. And again with pure CSS. The idea is to play with the paddings like that so the columns have equal widths. Here is the final result:

 1 .layout-d {
 2     width: 500px;
 3     margin: 0 auto;
 4     border: solid 1px #000;
 5 }
 6 .layout-d:after {
 7     content: "";
 8     display: block;
 9     clear: both;
10 }
11 .layout-d-column {
12     width: 33.33%;
13     float: left;
14     padding: 0 5px 0 5px;
15     -webkit-box-sizing: border-box;
16     -moz-box-sizing: border-box;
17     box-sizing: border-box;
18 }
19 .layout-d-column:last-child {
20     padding: 0 0 0 10px;
21 }
22 .layout-d-column:first-child {
23     padding: 0 10px 0 0;
24 }
25 .layout-d-column img {
26     width: 100%;
27 }
28 .layout-d-column p {
29     padding: 10px 0 0 0;
30     margin: 0;
31 }

The layout solution works with more columns as well. What you have to do is to update the width of .layout-d-column. For example the preview below uses 25%:

CSS: using float property

float property is one of those CSS rules which are somehow difficult to understand. Before a couple of days I had a problem with floating divs. I solved it and decided to write an article about the solution. The article contains some basics for the floating.[STOP]

Basic usage

The main function of the float property is to make the content floats around an element. I.e. if you need a text wrapping an image you should set float to the image. For example:

caption

caption

And the result is:

caption

caption

There are four possible values of float - left, right, none (default) and inherit. I think that they are self-explanatory.

What you should remember is that the floating continue until you clear it. In other words, no matter how many elements you add they will still wrap the floated block. In the example below the <footer> element should be below the image, but because there is no clearing it looks like that:

caption

caption

Clearing

There are mainly two ways to clear the floating. Adding an empty block element which has clear property set:

caption

caption

The other way is to use pseudo class after.

caption

caption

And the result is:

caption

caption

Navigation composition

Very often the float property is used for building navigation. I.e. a lot of front-end developers use unordered list with all its elements floated. For example:

caption

caption

Layout composition

float is used in most frameworks for layout composition. It’s easy to define content blocks and arrange them. For example here is three column layout:

Another common pattern is to style a page component. Let’s say that you have a user account teaser: <pre class="codepen" data-height="300" data-type="result" data-href="rozJx" data-user="krasimir" data-safe="true"><code /><a href="http://codepen.io/krasimir/pen/rozJx">Check out this Pen!</a></pre> <script async src=”http://codepen.io/assets/embed/ei.js”></script>

caption

caption

Problems

There are tons of great articles that explain the most common problems regarding float property. I don’t think that I’ll describe them in a better way so I’ll suggest to read this article or for example check out here. I think that most of the troubles in the usage of that css style are connected to the fact that the developer doesn’t know how the floating works. Of course there are cases where the bugs are because of the used browser or forgotten clear element. What I wanted to share is actually a problem that I had. Here is my layout - it’s just a list of info boxes and the idea is to have three per row:

caption

caption

The problem occurs once some of the elements has more text. All the boxes are floated to the left, but because the second one has a lot of text, its height is more than expected the result is not very good. I tried several solutions, but none of them were flexible enough. I had to find some trick to put clear: both after every third element. Of course I didn’t know the actual number of elements, I didn’t want to use javascript or set custom css classes. Then I realized that nth-child selector will do the job:

1 .info-box:nth-child(3n+4) {
2 	clear: both;
3 }