SitePoint Sponsor

User Tag List

Results 1 to 20 of 20
  1. #1
    SitePoint Member
    Join Date
    Aug 2011
    Posts
    5
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [Newbie] Basic question about specifity / element / order

    Having the simple code:

    HTML Code:
    <html>
    <head>
    <style type="text/css">
    #red p {
    	color: #F00;
    }
    .blue {
    	color: #00F;
    }
    </style>
    </head>
    <body>
    <div id="red">
    <p>Should be a red paragraph</p>
    <p class="blue">Should be a blue paragraph</p>
    </div>
    </body>
    </html>
    Why is the second paragraph still red? What's the solution to make it blue?

    Thanks.

  2. #2
    SitePoint Guru bronze trophy TheRaptor's Avatar
    Join Date
    Jul 2011
    Location
    New York
    Posts
    710
    Mentioned
    40 Post(s)
    Tagged
    0 Thread(s)
    In your stylesheet you are using #red p. The problem with this is that it targets all the p tags in the #red div and overrides your second line of css.

    There are a number of ways to fix this, one of them is to give each <p> a class and target them individually like so:
    Code:
    <html>
        <head>
            <style type="text/css">
                .red {
                color: #F00;
                }
                .blue {
                color: #00F;
                }
            </style>
        </head>
        <body>
            <div id="p-wrapper">
                <p class="red">Should be a red paragraph</p>
                <p class="blue">Should be a blue paragraph</p>
            </div>
        </body>
    </html>
    Or a more advanced method is to add :first-child to the #red div like so (first-child as it's name implies, will only target the first element of whatever you are selecting; in our case the <p> tag):
    Code:
    <html>
        <head>
            <style type="text/css">
                #red p:first-child {
                color: #F00;
                }
                .blue {
                color: #00F;
                }
            </style>
        </head>
        <body>
            <div id="red">
                <p>Should be a red paragraph</p>
                <p class="blue">Should be a blue paragraph</p>
            </div>
        </body>
    </html>

  3. #3
    SitePoint Member
    Join Date
    Aug 2011
    Posts
    5
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, but why does the '#red p' overrides the '.blue' class? That's what I don't understand .

  4. #4
    SitePoint Guru bronze trophy TheRaptor's Avatar
    Join Date
    Jul 2011
    Location
    New York
    Posts
    710
    Mentioned
    40 Post(s)
    Tagged
    0 Thread(s)
    Block level elements such as <div> and <h1>, <h2>, <h3> etc, have precedence over inline elements. You've given your <div> an id of #red and selected all the <p>'s in that div, and because you have given your <p> tag (an inline element) a class of .blue it doesn't have as much precedence and is therefore ignored.

  5. #5
    SitePoint Member
    Join Date
    Aug 2011
    Posts
    5
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    But <p> is also a block level element, as <div>...

  6. #6
    Mouse catcher silver trophy
    Stevie D's Avatar
    Join Date
    Mar 2006
    Location
    Yorkshire, UK
    Posts
    5,820
    Mentioned
    110 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by paul_damian View Post
    Ok, but why does the '#red p' overrides the '.blue' class? That's what I don't understand .
    Both '#red p' and '.blue' are targeting the paragraph. There's a conflict. One says it should be red, the other says it should be blue. Conflict resolution says ... if one declaration lists more IDs than the other, that one wins.
    '#red p' lists one ID, and '.blue' lists no IDs. So '#red p' wins, doing a victory jig over '.blue's dead body, and the paragraph turns red.

    If the red dec was just '#red' without the 'p' then it would be a different story. Then the '#red' declaration would not be specifically targeting the paragraph, but the paragraph's parent. The default colour is 'inherit' (ie, whatever the parent is), so if nothing else is specified for the paragraph, it is red. But then you have '.blue', which comes along and tells the paragraph not to inherit the colour of its parent, but instead to be blue. So then it's blue.

  7. #7
    Mouse catcher silver trophy
    Stevie D's Avatar
    Join Date
    Mar 2006
    Location
    Yorkshire, UK
    Posts
    5,820
    Mentioned
    110 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by TheRaptor View Post
    Block level elements such as <div> and <h1>, <h2>, <h3> etc, have precedence over inline elements.
    Say what? Styling on block-level elements does not win out over styling on inline elements in fact, it's usually the other way round.

    Code:
    p {color:red;}
    span {color:green;}
    
    <p>Here's a red paragraph <span>with some green words</span> in the middle</p>
    Styling declared on the inline element will almost always overrule styling declared on the parent element, because it's targeting the actual element rather than its parent.

  8. #8
    SitePoint Guru bronze trophy TheRaptor's Avatar
    Join Date
    Jul 2011
    Location
    New York
    Posts
    710
    Mentioned
    40 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Stevie D View Post
    Say what? Styling on block-level elements does not win out over styling on inline elements – in fact, it's usually the other way round.

    Code:
    p {color:red;}
    span {color:green;}
    
    <p>Here's a red paragraph <span>with some green words</span> in the middle</p>
    Styling declared on the inline element will almost always overrule styling declared on the parent element, because it's targeting the actual element rather than its parent.
    A <p> is a block-level element anyways (was coding a WP theme for a client while I posted that, multi-tasking was never one of my strong suits ). Totally messed that up, don't know what I was thinking .

  9. #9
    Community Advisor silver trophybronze trophy
    dresden_phoenix's Avatar
    Join Date
    Jun 2008
    Location
    Madison, WI
    Posts
    2,728
    Mentioned
    31 Post(s)
    Tagged
    0 Thread(s)
    Am sorry I think I have missed most of the post, the answer here is SPECIFICITY. I has nothing to do with block or inline.

    SPECIFICITY overrules the cascade.. no matter what!

    That means :
    A class will overrule a tag in the style sheet, an ID will in turn overrule a class and if you should ( perish the thought) write your CSS in the mark-up inside the tag itself it will overrule EVERYTHING ELSE.

    By the described order above :
    #red p {} will override rules like : p{}( a tag), .blue {}(a simple class), and even p.blue{} ( a class and tag) since you started with an ID and a tag... in order to override that rule.. you will need AT LEAST an ID and a tag. #red p {} (will target all the Ps and its not what we want so we need something like #red .blue {}

    expounding on this:
    if you had written:
    .red p {}
    .blue{}

    it will would not work as a class+ a tag is still > just a class

    HOWEVER this would work
    .red p {}
    p.blue{}

    AND THIS would not.

    p.blue{}
    .red p {}


    when the specificity total is the same (class+tag)=(class+tag) then rule that is latter the stylesheet wins.

    hope that clears this all up for you.

  10. #10
    It's all Geek to me silver trophybronze trophy
    ralph.m's Avatar
    Join Date
    Mar 2009
    Location
    Melbourne, AU
    Posts
    23,590
    Mentioned
    411 Post(s)
    Tagged
    6 Thread(s)
    For more information on specificity, check out the SitePoint CSS Reference. It has a nice summary of how specificity is calculated.

  11. #11
    SitePoint Member
    Join Date
    Aug 2009
    Posts
    3
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

  12. #12
    #titanic {float:none} silver trophy
    molona's Avatar
    Join Date
    Feb 2005
    Location
    from Madrid to Heaven
    Posts
    8,023
    Mentioned
    211 Post(s)
    Tagged
    1 Thread(s)
    I couldn't have said it better that Dresden did

    Thanks, Dresden, you saved my time

  13. #13
    SitePoint Member
    Join Date
    Aug 2011
    Posts
    5
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So, then what would be the finest soltution to achieve the following:

    HTML Code:
    <div id="firstdiv">
    <p>Some paragraph text</p>
    <p>Some paragraph text</p>
    <p>Some paragraph text</p>
    <div class="seconddiv">
    <p>Other paragraph text</p>
    </div>
    </div>
    #firstdiv p needs some formatting (eg bottom margin) which is not wanted on the <p> in the #seconddiv.

    What's the best way to address the "Other" <p> to change its CSS?

  14. #14
    It's all Geek to me silver trophybronze trophy
    ralph.m's Avatar
    Join Date
    Mar 2009
    Location
    Melbourne, AU
    Posts
    23,590
    Mentioned
    411 Post(s)
    Tagged
    6 Thread(s)
    What you want to do there is make a rule that only targets the <p> elements in the #firstdiv. You can do that with:

    Code:
    #firstdiv > p {margin-bottom: 30px;}
    That will only add bottom margin in the <p>s directly inside #firstdiv, and will leave those in .seconddiv alone.

    Be aware, though, that IE6 doesn't recognize the > selector, so you'd need a more long-winded solution to cover that browser, such as

    Code:
    #firstdiv p {margin-bottom: 30px;}
    #firstdiv .seconddiv p {margin-bottom: 0;}
    The first line will add bottom margin to all <p>s, and the second line will override the first line for the <p> inside .seconddiv.

  15. #15
    SitePoint Member
    Join Date
    Aug 2011
    Posts
    5
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ahh, that's where I was confused and wrong.

    #firstdiv .seconddiv p {margin-bottom: 0;}
    does the trick, but just
    .seconddiv p {margin-bottom: 0;}
    does not.

    Thank you all for your help!

  16. #16
    It's all Geek to me silver trophybronze trophy
    ralph.m's Avatar
    Join Date
    Mar 2009
    Location
    Melbourne, AU
    Posts
    23,590
    Mentioned
    411 Post(s)
    Tagged
    6 Thread(s)
    Quote Originally Posted by paul_damian View Post
    #firstdiv .seconddiv p {margin-bottom: 0;}
    does the trick, but just
    .seconddiv p {margin-bottom: 0;}
    does not.
    Yes, and the reason is one of specificity. An id (#) carries a lot more weight than a class (.), so the id wins out. So to make the override more specific, you have to include an id. It's now more specific because it contains an id and a class, which has more weight than just an id.

    I'd still go with the simpler solution, though, unless you must support IE6. Even then, you could put the IE6 style in a separate, IE-only style sheet, or serve it up with a hack, such as

    Code:
    * html #firstdiv p {margin-bottom: 30px;}
    * html #firstdiv .seconddiv p {margin-bottom: 0;}

  17. #17
    The CSS Clinic is open silver trophybronze trophy
    Paul O'B's Avatar
    Join Date
    Jan 2003
    Location
    Hampshire UK
    Posts
    39,777
    Mentioned
    158 Post(s)
    Tagged
    3 Thread(s)
    Quote Originally Posted by dresden_phoenix View Post
    and if you should ( perish the thought) write your CSS in the mark-up inside the tag itself it will overrule EVERYTHING ELSE.
    Except for rules using !important but I know what you meant

  18. #18
    #titanic {float:none} silver trophy
    molona's Avatar
    Join Date
    Feb 2005
    Location
    from Madrid to Heaven
    Posts
    8,023
    Mentioned
    211 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by Paul O'B View Post
    Except for rules using !important but I know what you meant
    Because !important is really !important... but it is better not to use it unless you have a terrific reason for it... and no, setting up the size of the characters is not a good reason

  19. #19
    SitePoint Wizard
    Join Date
    Oct 2005
    Posts
    1,763
    Mentioned
    5 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by Stevie D View Post
    Conflict resolution says ... if one declaration lists more IDs than the other, that one wins.
    I learned something reading this. I always though the cascading nature of CSS dictated that whatever rule came last won. I guess that isn't true. Thanks.

  20. #20
    #titanic {float:none} silver trophy
    molona's Avatar
    Join Date
    Feb 2005
    Location
    from Madrid to Heaven
    Posts
    8,023
    Mentioned
    211 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by cheesedude View Post
    I learned something reading this. I always though the cascading nature of CSS dictated that whatever rule came last won. I guess that isn't true. Thanks.
    That only happens when both rules have the same specificity level. Of course, you only notice it when you're trying to style the same property for the same element in bothy rules


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •