Confusion about selector priority


#1

<PLEASE USE THIS TEMPLATE TO HELP YOU CREATE A GREAT POST!>

<Below this line, add a link to the EXACT exercise that you are stuck at.>
https://www.codecademy.com/courses/learn-css-typography/lessons/css-typography/exercises/text-align?action=lesson_resume&course_redirect=learn-css

<Below this line, in what way does your code behave incorrectly? Include ALL error messages.>
From what I had read in the CSS Selectors lesson, an id selector (#[id] {}) overrides a class selector (.[class] {}) which overrides a tag selector (e.g. h1 {}). So how come in the linked exercise on Text alignment, the instructions work when I added the text-align: left; declaration to the h1 selector? The h1 element is a child of a div element that has been assigned the class “banner” and there is a text-align: center declaration within the CSS rule for that class (.banner). So shouldn’t that rule override the rule under the h1 selector and therefore the text should NOT have aligned to the left? What am I missing?

```

h1 {
color: white;
font-size: 28px;
font-family: Georgia;
text-transform: uppercase;
text-align: left;
}

vs.

.banner {
background-color: #4D00FF;
padding: 100px 0;
margin-top: 77px;
text-align: center;
}

see html starting at line 21:

Typography

While typography has been practiced for many centuries, digital font design is a relatively new discipline. There are some great examples of old-school fonts (also called typefaces) which have been adapted for use on digital displays. However, I would like to highlight a few of my favorite fonts that were created with screens in mind.

<do not remove the three backticks above>

#2

well you understanding of selectors overwriting is correct

the problem you are epxeriencing has nothing to do with it, the problem is that h1 is a block level element. When we use text-align center, text within that block is centered. so text within .banner gets centered, but block level elements (h1) are not affect by text-align


#3

Thank you for your response. I understand what you’re saying about h1 being a block-level element and that the text-align declaration is affecting the text within that block. I think I see where my understanding was off after I did a little test. Apparently the class has to be assigned directly to the element to override tag-level declarations about that element.

<h1>Typography</h1> will display text on the left of the screen (because the text defaults to left-alignment within the h1 box)

adding the CSS declaration h1 {text-align: center;} will center the h1 text within the box

if, however, I add a class directly to h1 (<h1 class="test">Typography</h1>)
and then add the CSS declaration .test {text-align: left;}, the h1 text will align left within the box because this class-level declaration overrides the tag-level declaration

but if that class were assigned to a parent element of h1 and not h1 itself:

<div class="test">
  <h1>Typography</h1>
</div>

the .test {text-align: left;} declaration does NOT override the tag-level declaration for h1, since the class is not assigned to h1 itself, but to its parent element.


#4
h1 {
    color: maroon;
}
.test h1 {
    color: orange;
}

The class selector has greater specificity so no matter what order these rules are written, the .test rule will win out. The same would be the case if the class was directly on the H1.


#5

yea, for example:

<h1 class="test">test</h1>

.test { color: red; }
h1 { color: pink; }

the text would be red, class selector is stronger.

if the class is on a different element, it doesn’t matter, given there is no conflict


#6

Ummm @stetim94,

It’s a missed-typo, I think you meant red :wink:


#7

yes, red indeed, let me correct that


#8

I’m quite interested with the topic myself. After reading through your posts, I think there are some parts you confused about.

Not necessarily.

As @stetim94 mentioned, your understanding of the hierarchy of selectors overwriting is correct.

Combining what @mtf and @stetim94 replied, let me illustrate this for you.


Using id & class selectors overwrite the tag selectors, that, you understand. One thing you overlook is specificity. The example given is to make H1 become Red.

You might think that,

HTML:

<div class="test">
  <h1>Typography</h1>
</div>

CSS:

.test { 
  color: red;
}
h1 { 
  color: yellow; 
}

The h1 is yellow, why it is not red? (since I’m targeting the .test class, the h1 should be the same?).
Reason: No it doesn’t work that way. You’re targeting the test class (so any elements that has the class, will be in color red), but not the h1 (h1 does not have the class).


To solve to this, you may think that the other way to make h1 red by using class selector (there are many other ways other than using class) is through:

  • Adding the test class into h1
  • Adding another new class (ie: red) into h1

Which is:

HTML:

<div class="test">
  <h1 class="red">Typography</h1>
</div>

CSS:

.test { 
  color: red;
}
.red {
  color: red;
}
h1 { 
  color: yellow; 
}

That will work.


Now, back to the specificity I mentioned. You can be very specific with your selectors and targeting their child/descendants. This is what @mtf mentioned about.

There’s no need to add any class to h1 to make it Red.

HTML:

<div class="test">
  <h1>Typography</h1>
</div>

CSS:

.test h1 { 
  color: red;
}
h1 { 
  color: yellow; 
}

By changing the selector to be more specific, adding the h1 after the .test, meaning target the h1 element, which is the descendant of .test class.

The h1 will turn red.

There is a benefit of specificity, you don’t have to add every different classes for every elements you want to change, that will be a lot.


So what if you wanted the .test class all in green, the rest of h1 yellow, but all the h1 under the divs of .test red?

Your CSS can be like this:

.test { 
  color: green;
}
h1 { 
  color: yellow; 
}
.test h1 { 
  color: red;
}

So, in your case about h1 vs. .banner

You can just add another specific selector into your CSS:

h1 {
   color: white;
   font-size: 28px;
   font-family: Georgia;
   text-transform: uppercase;
   text-align: left;
}

.banner {
   background-color: #4D00FF;
   padding: 100px 0;
   margin-top: 77px;
   text-align: center;
}

.banner h1 {
   text-align: center;
}

This will ensure only h1 under the class .banner is being centered. The rest of h1 will still be aligned to the left.

Add-in: another question you posted:

No. It will only overruled if the code is this way:

<div>
  <h1 class="banner">Typography</h1>
</div>

Where in this context, the class selector is more superior than h1 selector.


Oh well, sorry for the long post again, hope not making anyone’s eye bleed. :wink:

Good day. :slight_smile:


#9

Your thorough response is much appreciated. I totally get your explanations of chaining selectors (e.g. .banner h1) vs. creating a separate class.

I’m only a few days into studying html and CSS, so I’m in the information overload stage, but having a blast! I’m grasping individual concepts quickly, but sometimes relating all the principles can be confusing until I slow down and mull over specific examples like in this case.


#10

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.