After my article about frontend development where I particular focused on tools and javascript I will now focus more on CSS and styling. I can still remember the time when I started with web development and I used only inline styles. Now this is absolutely not done anymore. And that is very understandable considering that CSS has grown into a mature styling language nowadays and you don’t want to put all these logic in your html code.
A good frontend developer seperates logic (javascript), styling (css) and structure (html) and puts all this in different files. Today this might sound like common practice but not that long ago this wasn’t always the case. In this article I am going to show some tips and tricks about new (and not so) trends in the world of CSS. If you are a real frontend developer you might know all of this already but for everyone else who want to know how real frontend developers do it please keep on reading.
Pixels vs Em vs Rem
Do you know the difference between these? You might have seen them in your css files but how do they relate? I think everybody knows what pixels are. If not please read this first. Until very recently it was common to define all font sizes in pixels. But today this is not best practice anymore. Today you can better use em and rem units. In contradiction to pixels, rem and em are relative units. Pixels are absolute.
em: looks at the parent font size where 1 em = parent font size (px)
rem: looks at the root font size. So it is relative to the font size used in your HTML tag. 1 rem = root font size (px)
Example:
1 2 3 4 5 6 7 8 9 10 11 |
html { font-size: 20px; } h1 { font-size: 2rem; } div { font-size: 1.5em; } |
1 2 3 4 |
<div> <h1>My title</h1> Hello </div> |
In this example the root font size is 20 pixels. So the font size of h1 is 2 rem = 2 * 20px = 40px.
The font size of div is 1.5 em = 1.5 * 30 px because the parent of the div tag is the html. If you body had a font size specified it would be equal to the font size in your body tag.
If your h1 would have a font size of 2 em instead of 2 rem it would be 2 em = 2 * 30 px = 60 px.
Check out this JSFiddle example and play around with it.
Advance CSS Selectors
If you are a bit familiar with CSS you know the most common css selectors:
- #foo : Selects element with id ‘foo’
- .foo : Selects all elements which have a classname ‘foo’
- h1 : Selects all h1 elements
- h1.foo : Selects all h1 element which have a classname ‘foo’
- div.foo .bar : Selects all elements inside a div element with classname ‘foo’ that have a classname ‘bar’
But there are much more and I will dive into that now.
Which selector is applied?
Do you think that the latest selector always overrides the previous one that we wrote for the same element? If you keep your selectors simple then this might be the case but it’s not a rule. Which selector wins is defined by it’s specificity value. I see you thinking what the hell is this? It’s a special value that you can assign to every selector. The highest wins where ever it’s located in your css file. If two selectors have the same specificity value then the latest selector wins like you are used to. I am not going into too much detail about this here because there are some excellent websites explaining this in full detail:
Let me give you an example:
1 2 3 4 5 |
<ul id="summer-drinks"> <li class="favorite">Whiskey and Ginger Ale</li> <li>Wheat Beer</li> <li>Mint Julip</li> </ul> |
1 2 3 4 5 6 7 8 9 10 |
ul#summer-drinks li { font-weight: normal; font-size: 12px; color: black; } .favorite { color: red; font-weight: bold; } |
So what color do you think that this list element has? You probably think that ‘Whiskey and Ginger Ale’ is red but it is black! If you don’t believe me check it out yourself here on JSFiddle. So how can you make it red? You need to make the specificity value of the selector .favorite higher. You can do this by making him more specific.
1 2 3 4 |
ul#summer-drinks li.favorite { color: red; font-weight: bold; } |
The more unique (specific) you make the selector the higher it’s specificity value is. You can see which styles are applied in your browser css inspector.
It’s a good practice to make your css selectors as unique as possible. So don’t use selectors like .favorite but make it more unique like in the example above. This also avoids wrongly applied styles.
Attribute selectors
Now you know why and when a selector is applied let’s take a look at some more advance selectors. Attribute selectors let you target an element based on its attributes. With an attribute selector you can apply a style on a element that has a specific attribute with a specific value.
1 2 3 |
div[name="info"] { background-color: #333; } |
Every div that has an attribute name with the exact value info will have a background color. There are of course much more options available like:
[att*=”foo”] : attribute value should contain ‘foo’
[att^=”foo”] : attribute value should start with ‘foo’
.. etc
Child selector
The child selector is represented by the sign “>”. It allows you to target elements that are direct children of a particular element.
Example:
1 2 3 |
div > h2 { color: red; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<h2>Welcome on my page</h2> <div> <h2>Title 1</h2> <p>Some nice text</p> <h2>Title 2</h2> <p>Some nice text</p> <div> <h2>Title 3</h2> <p>Some nice text</p> </div> </div> <h2>Other stuff</h2> <p>Some nice text</p> |
In this example h2 element Title 1, Title 2 and Title 3 will be red. All other h2 elements have the default color. Check it out here.
Sibling combinators
There are two type of sibling combinators, adjancent and general.
Adjancent Sibling Combinator
Use the (+) symbol to target two elements that have the same parent and the second one comes directly after the first one. This can be useful when dealing with text for example when you want to add a top margin to all paragraphs directly after an h2 tag.
1 2 3 |
h2 + p { margin-left: 40px; } |
1 2 3 4 5 6 7 |
<h2>Welcome on my website</h2> <p> aecenas vestibulum at elit varius hendrerit. Maecenas feugiat aliquet elit sed sodales. Cras vel ex massa. Integer lectus erat, mattis ullamcorper luctus et, consequat quis sapien. Nullam tristique dolor diam, a pellentesque metus ultrices vitae. </p> <p> Praesent at ex tristique, ullamcorper ante ut, sagittis mauris. Vivamus dapibus felis eget lorem viverra pellentesque. Aenean in massa neque. Praesent malesuada erat massa, quis interdum sapien dapibus a. Sed porta gravida orci vitae sollicitudin. </p> |
This construction will give the first paragraph a left margin of 40px as you can see here.
General Sibling Combinator
Like the adjancent sibling combinator with the exception that the second selector doesn’t have to immediately follow the first one. Use the symbol (~) for this.
Pseudo-classes
This is a cool phenomenon because these or not real classes. These ‘classes’ are dynamically added to your elements on events like hover, active, focus etc. They are also automatically removed as soon as the event ends. But because they exist you can style elements based on events. For example when you hover over a div your can change its background color:
1 2 3 |
div:hover { background-color: red; } |
Here is a list of some pseudo-classes that can come in handy:
:hover | Activates when user moves cursor over element |
:visited | Links that have been visited |
:target | Can be used when you use anchors in your website. For example if an element has an anchor #about and you clicked on a link that points to this anchor this pseudo class becomes active and you can for example highlight the anchor. |
:link | Links that haven’t been visited yet. |
:lang() | Selects an element or link only if the language of that link or element matches. For example :lang(en). |
:focus | Element in focus (used in forms for example) |
:first-child | Selects first child of another element. For example you can apply a style only to the first item of a list. |
:nth-child() | Selects the nth child of another element. For example select the third list item :nth-child(3). Supports expressions like :nth-child(3n+4) which will select every third element starting from the 4th. Or :nth-child(even) to select all even children from the start. |
:nth-last-child() | Start counting from the last one |
:nth-of-type() | Will only match children that match the type in the selector but works like nth-child. For example p:nth-of-type(even) will select all even PARAGRAPH elements but not other type children like div. |
:enable | Is activated when element state is enabled |
:disable | Is activated when element state is disabled |
:checked | Is activated when element state is checked |
:active | Activates when user clicks on element |
:nth-last-type() | Same as nth-of-type but starts from the last one |
:empty | Element that has no content |
Negation pseudo-class
You can use :not() to select all elements except this. For example:
1 2 3 4 5 |
input:not([type="submit"]) { width: 200px; padding: 3px; border: 1px solid #000000; } |
Will select all input buttons except with type submit.
Pseudo-elements
Beside pseudo-classes we also have pseudo-elements. These are elements that do not really exist like first-line or text-block.
p::first-line => Selects the first line of a paragraph
p::first-letter => Selects the first letter of a paragraph
Last cool CSS trick!
Did you know that you can add content ::before and ::after elements using purely css?
1 2 3 |
<span class="token selector">img::after </span><span class="token punctuation">{</span> <span class="token property">content</span><span class="token punctuation">:</span> <span class="token string">"Another cool image</span><span class="token string">"</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> |
And that is not all yet. You can also create CSS counters. I am not going to dive any deeper anymore into CSS for now but as you see there is more to styling then just adding borders and background colors.