Don’t Ever Get Confused While Learning CSS
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.
- 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 —
:afterget a score of 1.
- Classes and attribute selectors —
input[type="text"]get a score of 10.
- ID’s —
#headerget a score of 100.
- Inline styles get a score of 1000.
!importantrules 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.
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
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).
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!
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?
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.
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-blockelements, 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-bottomof 25px and the bottom element has a
margin-topof 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
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 —
fixed work, and how they affect your layout.
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
static would be when you want to reset a previously changed value for
position is set to
relative have normal flow. Then what’s the difference between
static, you ask? The
relative property is basically
static on steroids. You get the option to use new properties with
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 —
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 is a powerful rule that can be used to place an element precisely where you want it.
relative elements, you can use the
left properties to set the location of
absolute elements. However, these values will be relative to the next parent element with
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
.parent are siblings and
.parent is positioned
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
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 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.
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.
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.