- 16 minutes read

CSS is fun. Nonetheless, many seasoned programmers approach me, asking me to help them with their CSS problem. This article is for you. It's not an in-depth tutorial. There are plenty of tutorials telling you every advanced feature of CSS. Try as I might, I couldn't do that. I'm not that familiar with CSS. But that's all right. I've watched many good developers struggle with CSS (including myself). You don't need an advanced tutorial. You need a compass and a map. Once you've got that, you know how to get along. So I decided a collection of strategies helping you to find your way in the dark.

You're still with me? Great. Let's start. If you're reading this article on your desktop or laptop PC, please open the developer tools. Depending on which browser you're using, the simplest way to do that is hitting the F12 key on Windows or ALT + CMD + I on macOS.

Which browser should you use for development?

Talking about the browser: I'd recommend using Google Chrome because of its superior developer tooling. However, if you're concerned about privacy - as you should! - please add a couple of ad blockers and a VPN. A good alternative is the Brave browser. I've installed several ad blockers in my copy of Brave, just to be sure, but at least Brave claims to protect your privacy. Brave is a sibling of Google Chrome. It's built on Chromium, maintained by a team lead by the creator of JavaScript, Brendon Eich. From a developer perspective, Brave doesn't match Chrome, but it's close.

The second best choice is Firefox. The developer tools of this browser have improved a lot during the last couple of years. Nowadays (i.e., January 2020), they are nearly as good as Chrome's dev tools. You'll notice the difference, but using Firefox to develop doesn't hurt. Privacy considerations make me use Firefox and Brave most of the time.

If you're using Chrome, Brave, or Firefox, you'll be able to follow this article without problems. I don't recommend using another browser. Most of them offer worse developer tools, and even if they don't, you won't recognize the screenshots.

Plunging in at the deep end

Please open the developer tools by hitting the F12 key on Windows or ALT + CMD + I on macOS. This time for real. :)

Now you should see this article in the upper part of the window, and developer info in the lower part of the window. You can customize this, so maybe the article is on the left-hand side, and the developer tools are on the right-hand side. Be that as it may, you'll recognize the windows and menus.


Modifying your page directly in the browser

We are mostly interested in the three menu items on the left-hand side. The first two are just images. Click on the first image - the one bearing the tooltip "Select an element in the page to inspect it." At first, nothing seems to change, apart from the menu item turning blue. But when you move the mouse to the web page, you'll see that blocks are selected. As you can see, these blocks are the HTML elements of the page. HTML elements often contain other HTML elements. Most HTML elements have a margin so that you can select both such a container element and each element within such a container.

After clicking on a text, your screen should look like this:

The menu "elements" of the developer tools is now active, showing HTML code on the left hand side and CSS rules on the right hand side. You can modify these CSS rules. Scroll to "font-size", click the value ("20px") and edit it. You can also use the cursor arrows to increase and decrease the font size.

"Inspect element" is a great tool to examine a page and to modify it. Among other things, it's useful to get rid of paywalls. Of course, you'll lose these changes after reloading the page. So make sure you copy successful changes to your CSS source code before forgetting what you've modified.

What can you do with CSS?

In a nutshell, CSS allows you to modify the look and feel of a web page. You cannot change the structure of the webpage. Often the structure is referred to as the "layout." CSS concentrates on the design of the page.

So you can modify the font of the text as well as the size, the margins, and the colors of every HTML element on the screen. Plus a plethora of advanced options you can see in the "Computed" tab. The "Styles" tab shows you which CSS rules are in your page; the "computed" tab shows the final result, after applying the defaults and every custom CSS rule.

Sometimes people go even further. I remember someone suggesting shifting an HTML element from the right-hand side to the left-hand side using CSS. Don't do that. To a limited extent, it's possible to define the position of screen elements using CSS. But more often than not, things get convoluted at this point. You can do it if you've written the HTML code to facilitate pushing elements around with CSS. However, if you know how to do that, you probably don't need this article. As long as you're learning, keep it simple.

At this point, I won't explain the CSS properties. Other people already have done that, so I simply point you to popular pages like w3schools or SELFHTML. I'd rather like to encourage you to play around with the developer tools.

Simplify it!

Most developers believing they don't understand CSS already have tried to tweak an existing CSS file - and failed. If that happened to you - don't worry, that happens to everybody. Every modern browser application has a huge CSS stylesheet. It's too much to understand it entirely. Most hurried developers modify the CSS stylesheet until trial-and-error yields the desired result. Do that a couple of years, and you end up with a mess. And that's probably precisely the CSS file that drove you nuts.

If you run into trouble, copy a small section of the HTML code or a small section of the CSS code. The idea is to reduce complexity. Now modifying the CSS rules should be easier. The problem with CSS is that three things can go wrong:

  • You've misspelled something.
  • You've used an invalid CSS selector. (I'll explain that word that in a minute).
  • There's another CSS rule overriding your CSS rule.

Simplifying the code eliminates the latter. Once you know your CSS rule works - at least in principle - you can apply it to the original web page, concentrating on finding the nasty CSS rule that breaks your rule.

CSS selectors

A minute ago, I asked you to modify the font size. If you did the same as I did, you've modified the size of the <p> tag. So every paragraph became larger, not only the paragraph you've selected. You've modified a global rule:

p { font-size: 20px; }

To make the CSS rules more specific, they begin with the "CSS selector." That's defining which HTML elements are influenced. As it happens, that's also the source of a lot of confusion and trial-and-error. The general idea is:

  • To select every instance of a certain HTML element, the CSS selector is simply the name of the HTML element. To modify the paragraph headers of this article, the rule starts with h2.
  • To select every HTML element bearing a certain CSS class, the CSS selector is a dot, followed by the CSS class.
  • You can also select an HTML element with a certain id. The CSS rule is a "#" followed by the id. If you're a JSF programmer, avoid this approach. JSF uses composite ids, so it's hard to predict the correct id. Plus, after modifying your page, you often end up with different ids.

These selectors are pretty sociable folks. Usually they come in groups:

  • Two selectors without a space between find HTML elements matching both. For example, h2.subheader finds every header of this blog, because I'm using <h2 class="subheader"> for the headers.
  • Adding a space between the selectors means that the second selector finds the HTML elements nested within the HTML container elements found by the first selector. For example, both h2 img finds the small anchor image behind the headers of this blog. (The image is only visible when you move your mouse over the header). It doesn't matter that the image is not a child, but a grandchild of the h2 element. The search finds every match recursively.
  • If you're interested in immediate children only, separate the selectors by a ">".

That only the beginning. There's a lot more to discover. However, most of the time, that's all you need. If you're still learning, the advanced stuff can be overwhelming. Don't worry. Most of the operators in the list are new to me, too. Just enjoy having a great toolbox at hand, even if most tools still look shiny and new due to lack of use.

When does which rule apply?

Again, that's where most casual CSS programmers despair. Why does the darned browser ignore my CSS rule? Luckily, it's straight-forward unless you're in a hurry:

  • The most specific rule wins. You make a rule more specific by adding a CSS selector.
  • If there are two rules with the same specificity, the last rule wins. That's why swapping the load order of CSS files usually results in a mess.
  • If everything else fails, you can add !important to the CSS rule. However, that's a bad idea. If you've started to make a CSS rule !important, usually you need to add other rules !important, too. That's only a last resort if you're using a CSS framework and can't modify the CSS rules for some reason. Even so, it's almost always possible to get rid of !important by making the CSS selectors more specific.

Why does the bloody application ignore my precious CSS rule?

Remains the question why your application still ignores the CSS rule you've added.

To find out, mark the HTML element you want to modify and add a filter to the CSS rules tab. Imagine you're interested in the font size. Filtering by font-size reduces the rules tab, at least a little:

As you can see, the tab only shows the rules influencing the font size. For some reason, the rules themselves are not filtered. Every attribute of the rule is displayed. So you often see a lot of stuff you're not interested in. Nonetheless, you should see your rule - the one that doesn't work - and every other rule. The CSS rule on top is the rule that wins.

In my example, that's a pretty nasty one. Or a great one, depending on your point of view. Let's examine the CSS selector closely:

.posted-on[_ngcontent-oaf-c38] { font-size: 14px; }

It begins straight-forward. The rule refers to a CSS element with the CSS class .posted-on. However, it's followed by something you won't find anywhere in the source code. This particular selector, [_ngcontent-oaf-c38], has been added by Angular. Every Angular component has - optionally - local CSS, and the strange selector is Angular's mechanism to make the CSS rule local. If you're scanning the source code, you will find nothing but .posted-on. There's no chance to find the [ng-content] bit, simply because it's not a part of your source code.

Similar surprises pop up with every sufficiently complex framework. For example, as I've already mentioned above, JSF uses composite ids. That's one of the (many) reasons why so many programmers consider JSF difficult.

So what to do when you encounter something like this?

Well, first of all, you have to recognize there's a computer-generated rule. In most cases, that's simple, because the rule looks a bit fishy. Most programmers prefer helpful names. If the CSS rule contains a two-digit number, it's probably a computer-generated rule.

Second, you have to make your rule more specific. Merely using the automatically generated selector is a bad idea. It may change with the next build. It's almost sure to be different after the subsequent rework of the HTML page.

So you should add at least two different selectors. Usually, I add the CSS classes of two parents I consider stable. It goes without saying that you need some experience and luck to choose a solid choice. Like so often, it's only an educated choice. In the case of my blog, if I were to override the font size of the post date, I'd probably choose this CSS selector:

content > article > .posted-on { font-size: 14px; }

Note there's no [_ngcontent-oaf-c38]. You don't need it. CSS simply counts the number of selector keywords. Three keywords are more specific than two keywords. That settles it.

Measuring size: CSS units

Defining the width and size is always a lot of fun in CSS. It's a good idea to define a root size and to define everything else relative to the root size. That's the idea of the rem unit. One rem is the height of the font of the root element.

Another popular unit is the point (abbreviated as pt). In real life, a point is 0.376 millimeters. How that translates to your computer screen? You never know. Points are good for printing but unpredictable on screens.

Of course, you can always use the good old pixel (aka px). The advantage of pixels is that the browser doesn't have to interpolate sub-pixels.

Two interesting - but widely unknown - units are vh and vw. That's one percent of the height or width, respectively. These units are useful to put something exactly into the middle of the screen.

Modern CSS also allows you to calculate. The syntax is a bit error-prone, but it's worth the pain. If you know your modal dialog is 500 pixels wide and 200 pixels high, and you want to put it into the middle of the screen, use this CSS rule:

.modal { position: absolute; left: calc(50vw - 250px); top: calc(50vh - 100px); z-index: 9999; }

However, like so often in the CSS world, there's also an alternative without calculations:

.modal { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }

Percentages are also a useful and popular CSS unit. However, using percentages is not without challenges. You have to know what the percentage refers to. Usually, it's the size of the parent element, but every once in a while, you'll see nasty surprises.

Putting it all together, I recommend using pixels for the root font size, and rem for the rest of your application. However, that's a matter of taste. More important is to choose a unit and to stick to it across the entire application.

There are also many resources on CSS units. I've collected two links for you: codetheweb.blog and www.tutorialbrain.com.

Local CSS

Modern applications are huge. So it isn't much of a surprise they need a lot of CSS. If you're a Java programmer, there's little you can do about it. Most enterprise Java applications have one or even several huge CSS files. Changing a CSS rule influences the entire program. Chances are you break a page you didn't even know it exists.

To solve this problem, add unique CSS classes to the HTML fragment you're working on. Adding this unique CSS class ensures only your page is modified.

Angular uses the same approach. As we've already seen above, local CSS is baked-in into the framework. Every Angular component has its own set of CSS rules. Components are small, so their CSS classes tend to be small, too. Plus, Angular guarantees these CSS rules are only applied locally.

Angular also has a global CSS file (styles.css). As a rule of thumb, this is a good place to put CSS rules modifying the external frameworks you're using. Everything else should go to the local CSS files.

You can use the same approach with most JavaScript frameworks. Have a look at the CSS modules project on GitHub.

Borders and boxes

One of the reasons why positioning elements is often so confusing is the box-sizing properties. CSS has two different approaches to calculating the width and height of an HTML element. Most CSS frameworks set this property to border-box. That's easier because it guarantees nested elements never bleed out of the container elements area. However, before adding a new CSS library, you should check if it uses the same box model. If you're interested in this topic, I'd like to send you to the examples and explanation of the box model on w3schools.com and to this detailed description of borders and boxes in CSS.


I've already warned you about positioning elements with CSS. Instead of using attributes like position: absolute; and top: 100px; I recommend using a CSS framework doing the layout for you. Traditional approaches are the grid systems of Bootstrap and Material Design. Newer approaches are flexbox and the CSS Grid Layout. The first three are one-dimensional frameworks, dividing the screen into columns and aligning your HTML widgets along these columns. Grid Layout is a two-dimensional approach, dividing the screen into both columns and rows.

It's always tempting to use the z-index. Don't try that at home. Sometimes, using z-index is your only choice, but it has a tendency to make your life difficult. Among other things, cross-browser support is bad. If you need to use the z-index, have a look at Veronika Ivhed's article on the z-index and Mozilla's resources on the topic.

Wrapping it up

The best approach to understanding CSS is playing around with it. That's why your browser offers great developer tools. I also recommend to keep it simple. There's a lot of advanced stuff, but most of the time you don't need it. Nonetheless, looking at the advanced stuff every once in a while is fascinating. It can even be a great motivation to keep learning. For example, it's possible to write a pure CSS slider - without a single line of JavaScript!

Dig deeper

CSS selector overview on w3schools.com

complete list of CSS rules on w3schools.com

Introduction to CSS selectory on Sitepoint

Examples and explanation of the box model on w3schools.com

Detailed description of borders and boxes in CSS

CSS units on codetheweb.blog

CSS units on www.tutorialbrain.com


CSS Grid Layout

Veronika Ivhed on the z-index

Mozilla explaining the z-index

a pure CSS slider

Another pure CSS slider

CSS selectors

CSS rule specificity

CSS specificity calculator