Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

WordPress From Bootstrap to WordPress Create Bootstrap Styled Theme Templates Creating a Portfolio Landing Page

Sarah Jee Watson
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Sarah Jee Watson
UX Design Techdegree Graduate 28,197 Points

How can you style individual items in the loop?

So I have the Portfolio landing page, all good. But I's like to style every first, second and third portfolio item (on the preview/landing page).

I can't use nth-child as there is no class to attach it to. I presume I need to add a class to each loop item?

ie.

portfolio entry one  = Class 1 
portfolio entry two = Class 2
portfolio entry three = Class 3
portfolio entry four = Class 1 
portfolio entry five  = Class 2
portfolio entry six = Class 3
and so on, repeating.. 

How do I do this?

Hi Sarah,

Are you talking about the "portfolio grid w custom posts" page?

Have you differed from the video? Post what changes you have made, if any.

In this video it was 4 per row but you seem to have 3 per row.

Sarah Jee Watson
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Sarah Jee Watson
UX Design Techdegree Graduate 28,197 Points

Hi Jason,

Yes the "portfolio grid w custom posts". I have differed in that I have two posts (images) per row for 4 rows.

Here's my code:

<div class="container"> 
    <div class="row">        
         <!-- Loop though projects -->
         <?php 
             $args = array(
                 'post_type' => 'project'
             );
                  $the_query = new WP_Query( $args );
          ?>
          <?php if ( have_posts() ) : while ( $the_query->have_posts() ) : $the_query->the_post(); ?>  
<a href="<?php the_permalink(); ?>">

    <div class="col-sm-6 project-entry">
             <!--Add thumbnails to potfolio items and resize for responsive-->
             <?php
                 $thumbnail_id = get_post_thumbnail_id();
                 $thumbnail_url = wp_get_attachment_image_src( $thumbnail_id, 'thumbnail-size', true);
                 ?>
             <!--Link images and titles to individual portfolio page -->  
                <p>
                     <img src="<?php echo $thumbnail_url[0]; ?>" alt="<?php the_title();?> project image"></p>
                 <div class="project-text">   
                <h4><?php the_title(); ?> | <?php the_field('project_type_name_'); ?></h4>
                <p><?php the_field('brief_description_'); ?></p>
              </div>
        </div></a>
     <!-- Add line break after 2 portfolio entries -->
     <?php $portfolio_count = $the_query->current_post + 1; ?>
     <?php if ( $portfolio_count %2 == 0 ): ?>
    </div>
        <div class="row">
        <?php endif; ?>
        <?php endwhile; endif; ?>
        </div>
</div>

And the CSS:

.project-entry img {
    width: 100%;
    margin: 30px 0;
    position: relative; 
    }

.project-text {
    position: absolute;
    z-index: 1;
    top: 7%;
    color: #fff;
    margin-right: 13px;
    padding: 24% 0;
    background: url('img/project-dark-grey.png');
    height: 381px;
    visibility: hidden;
    }

.project-entry:hover .project-text {
    visibility: visible;
    }

Each project-entry is an image. When you hover over the image it displays another image over the top with the project-text on top of that. This works great, except I want to use a different background image for every first, second and third project. So essentially, I'm trying to change this in the .css, to a different image:

.project-text {
background: url('img/project-dark-grey.png');

5 Answers

You should be able to accomplish this with nth-child if I'm understanding it right.

I think you want projects 1, 4, 7, ... to have a certain background image.
projects 2, 5, 8, ... to have another bg image
and project 3, 6, 9, ... to have yet another bg image
but they are laid out in rows of 2.

Let me know if I have misunderstood and I can revise my answer.

There's a few different ways to approach this. In any case, I would set the first background image in your .project-text rule while you're setting all the other common styles. Then you can override this background-image for the 2nd and 3rd projects and every 3 of those.

Probably the easiest way is to have a single row div with all the posts in it. This means you would take out the if that's adding more row divs. You'd want to use nth-child on the links since these are the direct children of the row div.

.project-text {
  /* common styles for all */
  background: url('path/to/bg1.png');
}

/* selects .project-text within links 2, 5, 8,... */
/* I switched to background-image here in case you need to add more background properties to the earlier rule */
/* If you use the shorthand again here to only change the background image then you will lose any other previously set properties */
.row a:nth-child(3n + 2) .project-text {
  background-image: url('path/to/bg2.png');
}

/* selects .project-text within links 3, 6, 9,... */
.row a:nth-child(3n + 3) .project-text { /* same as 3n */
  background-image: url('path/to/bg3.png');
}

If you'd like to keep the row breaks as is then I did figure out the selectors needed for that. The selectors are not very straight forward because the pattern is more involved. Here's a codepen demo illustrating how to do it with multiple row divs: https://codepen.io/anon/pen/EKPoab?editors=1100

Let me know if you have any questions about it.

You did ask about adding classes in the loop. You could do it this way too and add one of three classes to your project-text divs and then target those classes to change the background image.

I would only do this if you need to support older browsers that don't have support for nth-child.

Let me know if you still want to know how to do it this way and I can add it to my answer.

Here's my idea for adding classes in php. I didn't test this so let me know if it needs some fixing.

Your css could be something like:

.project-text {
  /* common styles for all */
  background: url('path/to/bg1.png');
}

.bg2 {
  background-image: url('path/to/bg2.png');
}

.bg3 {
  background-image: url('path/to/bg3.png');
}

Now it's a matter of echoing the bg2 class if the post is in the 2, 5, 8,... pattern, or echo bg3 if it's in the 3, 6, 9,... pattern, or don't echo because it's in the 1, 4, 7,... pattern.

I would move the assignment of the $portfolio_count variable to the top of the loop so you can make use of it for the class echoing.

<?php
  if ( have_posts() ) : while ( $the_query->have_posts() ) : $the_query->the_post();
  $portfolio_count = $the_query->current_post + 1;
?> 

Then you have to figure out which pattern the current post is in.

The 2, 5, 8, numbers are all 1 less than a multiple of 3. You can therefore add 1 to the post number and see if that is a multiple of 3 to know if it's in this pattern.

the 3, 6, 9, numbers are all multiples of 3 so you can simply check if the post number is a multiple of 3 to know if it's in this pattern.

<?php
  if (($portfolio_count + 1) % 3 == 0) { // if adding 1 results in a  multiple of 3 then  it was in the 2, 5, 8,... pattern
    $class = "bg2";
  } else if ($portfolio_count % 3 == 0) { // if it's  a multiple of 3 then it was in the 3, 6, 9,... pattern
    $class = "bg3";
  } else { // it's in the 1, 4, 7,... pattern. unset $class so nothing will be echoed
    unset($class);
  }
?>
<div class="project-text<?php if (isset($class)) { echo " " . $class; }?>"> 
Sarah Jee Watson
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Sarah Jee Watson
UX Design Techdegree Graduate 28,197 Points

HI Jason, Thank you for your responses. Just looking at it now. I guess if classes are more supported then that would be the best option?

Sarah Jee Watson
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Sarah Jee Watson
UX Design Techdegree Graduate 28,197 Points

The second option (codepen) works a treat. I see from caniuse.com that nth-child is only partially support for IE8. Is it generally best to find another way or are people not really building for IE8 any more?

It really depends on your visitors and what you're doing.

In terms of visitors, if you happen to know that you'll have a significant number of ie8 users then you should consider a fallback or different way of doing it.

In terms of what you're doing, I'll use rounded corners and border-radius to achieve that as an example. In my opinion, it's ok if a small amount of ie8 users see square corners instead of rounded ones. It's not critical to the functioning of the site. In this case, I would not worry about ie8 users.

However, if you were doing something that was going to lead to a badly broken layout in ie8 then I'd consider a fallback or alternative way of doing it.

In your case, will it be bad if a visitor sees the first background image for all projects? If yes, then maybe you should go the route of adding in classes with php. If no, then use nth-child so you don't have to have all these extra classes in your html.

I'll go ahead and add onto my answer how to add the classes with php. Even if you don't use it, it may be useful to you later or to someone else.

Sarah Jee Watson
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Sarah Jee Watson
UX Design Techdegree Graduate 28,197 Points

Thanks again Jason. It' just a background texture so in this case it's not the end of the world if the first one displays instead. I've used the first option but will revisit the classes just to see how that works too.

Sarah Jee Watson
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Sarah Jee Watson
UX Design Techdegree Graduate 28,197 Points

Update: (Jason Anello - just throwing this out there in case you're still into problem solving... :) )

This worked beautifully until I added a new project via ACF. It adds the new project to the front (so the first item on the page). The background image still displays and the link is in tact, hover the rollover image is only covering 1/4 of the background image (all others are ok) and the rollover image colours stop working after the first 6. Any ideas where I should be looking to rectify this?

Nothing has changed in the code or css - just the new 'project' via ACF.

<?php get_header( 'sml' ); ?>

<div id="project-img-bg">
   <div class="container">
       <div class="row">

           <div class="col-md-12">
                <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>



                    <?php the_content(); ?>

                <?php endwhile; else: ?>

                    <div class="page-header">
                        <h1>Oh no!</h1>
                    </div>

                    <p>You have clicked on a link that is missing.</p>
                    <p><a href="<?php  echo get_site_url(); ?>">"Go home..</p>
                <?php endif; ?>

           </div>

        </div>

   </div>

<div class="container"> 
    <div class="row"> 

         <!-- Loop though projects -->
         <?php 
             $args = array(
                 'post_type' => 'project'
             );

             $the_query = new WP_Query( $args );

          ?>

          <?php if ( have_posts() ) : while ( $the_query->have_posts() ) : $the_query->the_post(); ?>  
<a href="<?php the_permalink(); ?>">



    <div class="col-sm-6 project-entry">
             <!--Add thumbnails to potfolio items and resize for responsive-->
             <?php
                 $thumbnail_id = get_post_thumbnail_id();
                 $thumbnail_url = wp_get_attachment_image_src( $thumbnail_id, 'thumbnail-size', true);
                 ?>

             <!--Link images and titles to individual portfolio page -->  
                <p>
                     <img src="<?php echo $thumbnail_url[0]; ?>" alt="<?php the_title();?> project image"></p>
                 <div class="project-text">   
                <h4><?php the_title(); ?> | <?php the_field('project_type_name_'); ?></h4>

                <p><?php the_field('brief_description_'); ?></p>

            </div>
        </div></a>



     <!-- Add line break after 2 portfolio entries -->
     <?php $portfolio_count = $the_query->current_post + 1; ?>
     <?php if ( $portfolio_count %2 == 0 ): ?>

    </div>

        <div class="row">

        <?php endif; ?>
        <?php endwhile; endif; ?>
        </div>

</div>

<div class="dotted-border-bottom"></div>
   <!-- Footer -->   

    <div id="bg-footer">

    <div class="container">


        <?php get_footer(); ?>

    </div>      
.project-entry img {
    width: 100%;
    margin: 30px 0;
    position: relative; 
    }

.project-text {
    position: absolute;
    z-index: 1;
    top: 20px;
    color: #fff;
    margin-right: 13px;
    margin-top: 10px;
    padding: 14% 0;
    background: url('img/project-coral.png');
    height: 250px;
    visibility: hidden;
    }

/* selects .project-text within links 2, 5, 8,... */
/* 3n + 3 is the same as 3n */
.row:nth-child(3n + 1) a:last-child .project-text,
.row:nth-child(3n + 3) a:first-child .project-text {
  background: url('img/project-dark-grey.png');
}

/* selects .project-text within links 3, 6, 9,... */
.row:nth-child(3n + 2) a:first-child .project-text,
.row:nth-child(3n + 3) a:last-child .project-text {
  background: url('img/project-light-grey.png');
}

.project-entry:hover .project-text {
    visibility: visible;
    }

.project-text p {
    padding: 0 10%;
    }

.project-text a {
    color: #fff;
    }

.project-entry {
    text-align: center;
    }