Table of Contents
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.
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:
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:
400
px
;
3
height:
200
px
;
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:
400
px
;
3
height:
200
px
;
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
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:
360
px
;
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
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:
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.
Of course instead of text you could use another image. They both will take exactly 50% of the wrapper.
Layout C - a bit complex
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.
Layout D - many columns and space between them
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:
And the result is:
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:
Clearing
There are mainly two ways to clear the floating. Adding an empty block element which has clear property set:
The other way is to use pseudo class after.
And the result is:
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:
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>
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:
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
(
3
n
+
4
)
{
2
clear:
both
;
3
}