Don’t Ever Get Confused While Learning CSS

Image credit:

I’ve been working on small-time “web development” projects for several years now. Recently, I noticed a surprising trend. I realized that I’d always start with an idea and end up using a framework or straight up install Wordpress and use one of their templates. All I could really do was read existing code and modify bits and pieces to suit my requirements. Mine was a classic case of illusory superiority.

I discovered that I had never really understood CSS. If given a design and asked to code up the same using HTML and CSS from zero, I’d go blank the moment I encountered a minor complication. Ergo I decided to stop being lazy, roll up my sleeves and dive deep into learning CSS.

After two weeks of intensive studying and practice, I can say that I’m above average with CSS. CSS is vast and someone who calls himself/herself a pro doesn’t really know what they’re talking about.

Throughout my learning, I experienced frustration countless times and had to comb through the web to grasp important concepts. Here, I’ve laid out answers to few of the quirky problems I faced while learning CSS. I’ve also tried my best to clear up a couple of important concepts for all you new learners out there.

Should I Use ID’s or classes?

When you’re starting out, it might seem like as far as CSS is concerned, using classes and using ID’s is the exact same thing.

You might’ve read that ID’s are supposed to be used only once and classes can be used multiple times. Surprisingly, when you mistakenly use ID’s more than once, the CSS works just fine. Then you google this phenomenon and end up feeding yourself conflicted information based on reading developers’ personal preferences.

Turns out everyone is kinda right…Err, what?

  • CSS does not care which one you use, as far as applying styling.
  • JavaScript (I know this was about CSS, but just letting you know) though, cares very much about ID’s and this is where the uniqueness of ID’s is important. JavaScript will only find the first element with that ID. It is also noticeably faster to find an ID than a class in JavaScript.
  • ID’s have an infinitely higher specificity value than any other selector. If there is an element with an ID and a class and they both apply styles, the styles applied by the ID will take precedence over those applied by the class. This can be useful, albeit in rare cases.

As a rule of thumb — use ID’s on things you absolutely know there’ll only ever be one of and will not benefit from properties from a class name shared with other elements.

What’s this CSS Specificity and why is it so complicated?

CSS specificity is one of the most important tools in your tool bag to debug instances when styles just won’t apply to the element you want them to be applied to. In real web pages with multiple contributors, there’re often style rule-sets from multiple places targeting the same element. The browser always chooses the CSS rule with the higher specificity in case of any conflicts.

Some smart folks out there have devised a quick trick to determine the specificity score of any rule. Remember: The rule with the higher specificity score wins.

  • Elements and pseudo-elements — a, div, body:before:after get a score of 1.
  • Classes and attribute selectors — .someClass, input[type="text"] get a score of 10.
  • ID’s — #someID, #logo, #header get a score of 100.
  • Inline styles get a score of 1000.
  • !important rules get a score of . They’re more powerful than inline styles and can only be overridden by the cascade (rules written later in the stylesheet).
  • In case of two rule-sets having the same specificity, the last rule-set is the one that counts.

If you’re still confused, this awesome video by Tuts+ Code explains CSS specificity using examples.

Everything was fine until I added padding and borders. Then, all hell broke loose.

To achieve the layouts you want and really understand CSS-based web design, you need to understand that every element on a web page is really a rectangular box, even if it appears to be a different shape.

The default box model in CSS is content-box and if a developer is not really clear about how it works, it can lead to unexpected results. The content-box box model calculates the dimensions of an element in a weird manner, that is, it isn’t simple WYSWYG (what you say is what you get). In case you’ve applied padding or a border to an element, the final dimensions of the box will not be same as the one you specified.

The default box model — box-sizing: content-box

Final width: width + padding-left + padding-right + border-left + border-right

Final height: height + padding-top + padding-bottom + border-top + border-bottom

It is possible to do a bit of arithmetic and figure out what values to give for width, height, padding and border to get a final box with a width and height of your choice. However, this would only work for fixed-width websites. In today’s world of responsive and mobile-first designs, the same math doesn’t apply anymore.

The release of CSS3 finally gave web designers an alternative to the classic box model, the box-sizing rule. The new rule could take three values — content-box(the classic box model, a frenemy), border-box(our current best friend) and padding-box(the friend we remember rarely — supported only by Firefox as of now).

With box-sizing: border-box;, we can change the default box model to one where the element’s specified width and height are not affected by padding or borders. You might say that with box-sizing: border-box, the padding and border press their way inside the box rather than expand the box. This is a box model you can count on!

The border-box model

Say you wanted a box of width 400px and height 300px. You also want the box to have a padding of 20px on all sides and a solid black border 3px thick. You don’t want the box to expand beyond the width and height you have specified nor do you want to go through the trouble of calculating stuff manually. So what do you do?

Notice the difference between border-box and content-box?

By now, you must’ve understood how important box-sizing: border-box is for web designers. It is so useful that it has found its way into many stylesheets as the default box-sizing method and I think that’s a good way forward. You can also make the border-box model apply to all your elements using the universal selector *.

What’s that weird space between my inline-block elements?

inline-block elements are extremely useful and you’ll find yourself using them quite often. Simply put, inline-block elements are like inline elements but they can have a width and a height.

However, you might or might not have noticed a weird side effect of using inline-block elements. A series of such elements written just like you’re supposed to write them will have spaces in between them.

Why the weird white gaps?

In the case of navigation, you always want to avoid those little unclickable whitespace gaps between menu items. Here’s how to fight those gaps.

  • Remove the spaces: Minimized HTML, comments between consecutive tags, or one of the many funky hacks will do the trick.
  • Negative margin: You can put the items back into place using a negative margin of 4px. You may need to adjust this based on the parent’s font size.
  • Skip the closing tags: It’s optional to close certain tags in HTML5 and when you do so with inline-block elements, the white space isn’t visible anymore. However, you should know that code with closing tags is much more readable and easy to follow.
  • Set the font size to zero: When the font size is zero… isn’t it obvious? Don’t forget to override this with a custom font size for your element though.

See all the methods above in this pen by Chris Coyier below. Feel free to play around and truly understand what’s happening.

What the heck are collapsing margins?

Don’t know what I’m talking about? Collapsing margins are real and here’s where you’ll probably encounter the phenomenon.

  • When two vertical margins come in contact with one another: If one margin is greater than the other, then that margin overrides the other, leaving one margin. In the pen below, you have two elements stacked on top of one another. The top element has a margin-bottom of 25px and the bottom element has a margin-top of 50px. Simple right? The total margin between them will be 75px. Except, it won’t be. The bigger margin of 50px will just override the 25px margin and all you will have left is a total margin of 50px between the two elements. If you try to be smart and apply equal margins, just one of them would be applied and you won’t feel like you’re that smart anymore.
  • When a margin of a child element crosses the margin of its parent: In the pen below, your natural inclination will be to expect the total margin to be the sum of the parent and child margins. However, the child margin will get overridden by the parent margin.

So how do you fix collapsing margins?

There’s a way around collapsing margins when the margin of a child element crosses the margin of its parent — put something solid between the parent and the child like some padding or a border and the margins won’t collapse anymore.

It’s not so simple to fix top and bottom collapsing margins. There’re a few hacks out there which make use of clear: both and overflow: hidden. However, one should understand that these are nothing more than hacks and come with their own set of undesirable side effects. Simply put, it is better to avoid them altogether than to fix them.

“As a developer gets better they try to be less clever. I know where using IDs can be a pain so I save myself the hassle by not using them, same with collapsing margins; no one gets points for taking the more complex route. I honestly believe that if anything with caveats or potential ‘gotchas’ can be avoided they should be.”
— Harry Robert

Harry Robert offers a simple way of avoiding collapsing margins altogether by defining all your margins in one direction. He’s smart, and we all should be too.

I want to horizontally center this thing on my web page. But, how?

There’re two major rules web designers use to horizontally center stuff: text-align: center; and margin: 0 auto;. Most people know about these two rules. However, very few new learners know about when to use which rule and just rely on putting up whatever works.

text-align: center; can be used to horizontally center the content of inline elements, within a block-level parent element. This works for all inline elements whatsoever (inline, inline-block, etc.) such as h1, h2, p, etc.

margin: 0 auto;, on the other hand, is used for horizontally centering a block-level element with a known width. This’ll work irrespective of the width of the block level element, or the parent (except those with 100% width — those wouldn’t need centering).

Bonus: You can center whatever you want in whichever way (horizontally, vertically) you like using CSS. Literally, anything. However, for the scope of this article, I’ve focused on centering stuff horizontally since that is what is required in most cases. Don’t worry though, here’s a link to the ultimate CSS centering guide.

I’m having a tough time figuring out CSS positions.

Note: CSS positions is one area where I spent a lot of time trying to understand what was really happening and I think most of you did too. So let’s be clear about positions.

CSS positioning is commonly misunderstood. When you’re starting out, and you’re faced with a layout bug, you’ll be tempted to apply different values to the position property until you get the one that works and magically fixes your layout. Just because you lucked out once doesn’t mean you can rely on that always.

To truly understand the position property, you need to know how different values — static, relative, absolute and fixed work, and how they affect your layout.

position: static;

static is the default value of the position property for every element on a web page. Such elements have what is known as the normal flow, that is, they appear where they normally would in the document. The only time you would have to explicitly set an element’s position to static would be when you want to reset a previously changed value for position.

position: relative;

Elements whose position is set to relative have normal flow. Then what’s the difference between relative and static, you ask? The relative property is basically static on steroids. You get the option to use new properties with relative — top, right, bottom and left (there’s one more called z-index but let us leave it out for now).

relative elements are in practice relative to themselves. Calm down, it’s not that confusing. Setting position: relative on an element and not using the other positioning properties — top, right, bottom and left, is exactly the same as position: static. When you use top: 20px on a relative positioned element, it’ll shift it’s position down from where it would normally be. Simple, eh? Here’s an example to make it simpler. Feel free to explore.

Notice how the element with .red has a relative position and when top: 10px and left: 10px are assigned to it, it shifts relative to itself. The element with .green has a relative position too. However, it behaves in the same manner as a static element without the other positioning properties.

You’ll see next that position: relative is also used along with position: absolute to perform some pretty cool CSS magic.

position: absolute;

position: absolute is a powerful rule that can be used to place an element precisely where you want it.

Just like relative elements, you can use the top, right, bottom and left properties to set the location of absolute elements. However, these values will be relative to the next parent element with relative (or absolute) positioning. In case of absence of such a parent element, it’ll be placed relative to the page itself.

You can see in the example above that .uncle and .parent are siblings and .parent is positioned relative. Since .red is absolute positioned and has the top: 30px; rule, it is taken out of normal flow and is shifted 30px down from the top relative to it’s nearest relative parent, which in this case is .parent.

Something you always need to keep in mind is that absolute positioned elements are taken out of normal flow. They don’t affect other elements and other elements are not affected by it. This might prove to be a boon or a bane depending on what you’re trying to achieve.

position: fixed;

position:fixed is rarely used nowadays. An element that is positioned fixed has it’s position set relative to the browser window (also known as the viewport). Since the viewport doesn’t change even when the browser window is scrolled, a fixed element will stay right there.

In the example attached above, we target the .red element again. It has now been positioned fixed. Rules — top: 30px and left: 20px make it stay there always. Try scrolling the page and see for yourself.

The position: fixed is rarely used nowadays because of the need to make webpages look consistent across devices. Back in the not so good old days, it was generally used to position stuff like sidebars.

What else?

These were just few of the things I had problems with while learning CSS. I’ve tried my best to summarize the most important ones here. As I continue learning CSS and move forward with learning JavaScript and it’s frameworks, you can expect to see more posts about some pretty interesting stuff soon.

That’s it for now. Thank you for reading! Responses are most welcome and I would love to know what other problems you faced while learning CSS.

Spread this story by sharing it on Twitter or Facebook. You can also find me on Twitter, LinkedIn & GitHub or shoot me a good ol’ email.