Search code examples
csscss-selectors

Issue with CSS :first-of-type :first-letter


I've set my page to create a large drop-cap letter on the first paragraph of content. This works as expected, but when I have another div with a specified class before my affected elements, it makes the drop cap disappear.

See examples...
Correct display: http://jsfiddle.net/KPqgQ/
Incorrect display: http://jsfiddle.net/d73u9/

I have the following code in my page:

<section id="review">
  <div class="content_right"></div>
  <div class="content_left">
    <p>text</p>
    <p>text</p>
  </div>
  <div class="content_left">
    <p>text</p>
    <p>text</p>
  </div>
</section>

With the following CSS:

   #review .content_left:first-of-type p:first-of-type{
        padding-top:10px;
    }

    #review .content_left:first-of-type p:first-of-type:first-letter{
        float: left;
        line-height:90%;
        padding-right: 15px;
        padding-bottom: 10px;

        font-family: "Georgia",_serif;
        font-weight: bold;
        font-size: 60px;
        color:black;
    }

to create a drop-cap large first letter.

This code works when I remove the "content_right" div, but with it there, the CSS isn't working. I thought I had the correct order regarding declarations, but I must be missing something.

Does anyone know why this isn't working as intended?


Solution

  • This is working as intended as the :first-of-type selector actually selects the first of a specific type of element (section, div, span etc.) and doesn't actually select the first of a type of a class.

    Alternatives

    The '~' Fix

    The tilde '~' workaround mentioned here.

    /* Targets all paragraphs */
    p 
    {
            display: block;
            clear: both;
    }
    
    /* Targets all paragraphs within divs in #review */
    #review div p
    { 
            padding-top:10px;
    }
    
    /* Targets the first letter within each paragraph */
    #review div p:first-letter{
            float: left;
            line-height:90%;
            padding-right: 15px;
            padding-bottom: 10px;
            font-family: "Georgia",_serif;
            font-weight: bold;
            font-size: 60px;
            color:black;
    }    
    
    /* Removes the padding from all except the first paragraphs */
    #review > div ~ div > p ~ p, 
    #review > .content_left ~ .content_left p:first-of-type 
    {
            padding-top: 0px;  
    }
    
    /* Removes the first letter stylings of the non-first paragraphs within 
       .content_left classes */
    #review > .content_left ~ .content_left p:first-of-type:first-letter, 
    #review > div ~ div > p ~ p:first-letter 
    {
            float: none;
            line-height:90%;
            padding-right: 0px;
            padding-bottom: 0px;
            font-family: "Georgia",_serif;
            font-weight: normal;
            font-size: 12px; 
    }
    

    Example using '~' Method

    (Thanks to BoltClock, for helping me along with this and it is his method after-all.)


    Switching div Order

    Moving the .content_right div behind the .content_left sections, as they are floats and you could still maintain the same layout.

    Code:

    <section id="review">
        <div class="content_left">
            <p>text</p>
            <p>text</p>
         </div>
         <div class="content_left">
            <p>text</p>
            <p>text</p>
         </div>
         <div class="content_right"></div>
    </section>​ 
    

    Example of switching order:


    Using the :nth-of-type selector

    Using the :nth-of-type selector to select the proper div.

    Code:

    #review .content_left:nth-of-type(2) :first-child
    {
        padding-top:10px;
    }
    
    #review .content_left:nth-of-type(2) :first-child:first-letter
    {
        float: left;
        line-height:90%;
        padding-right: 15px;
        padding-bottom: 10px;
        font-family: "Georgia",_serif;
        font-weight: bold;
        font-size: 60px;
        color:black;
    }  
    

    Example using :nth-of-type