How to conditionally apply html code after every 3 posts?

I need to apply the following html line (that does a clearfix ) after every 3 posts are rendered in my index.html template.

<div class="clearfix"></div>

Here’s the relevant code in the index.html template that loops through all the posts and renders a summary with image.

    {{ range first 410 (.Data.Pages.ByDate.Reverse) }}        
    <div class="col-sm-4">
      <div class="article">
        <a href="{{ .Permalink }}">
          <img class="img-responsive" src="{{ $.Site.BaseURL }}media/img/{{ with .Params.image }}{{ . }}{{ else }}default.jpg{{ end }}" alt="{{ .Title }}" />
          <h5>{{ .Title }}</h5>
        </a>
      </div>
    </div>
    <!-- after every 3rd, 6th, 9th, 12th... etc post, I need to render that clear fix here. -->
    {{ end }}

In C#, the language I am familiar with, I would use a counter to keep track of the number of posts renders, and then do a Modulo operator check like so.

if ((counter % 3) == 0)
    {
	// render the clearfix html here.
    }

How would I do this using the Go templating language code?

Thank you!!

Hugo provides a modulo template func:

{{ range $k, $v :=  first 410 (.Data.Pages.ByDate.Reverse) }}  
    {{ if mod $k 3 | eq 0 }}
    {{ end }}
{{ end }}

We also have a modBool, so the above can be shorter:

{{ if modBool $k 3 }}

And, btw: It is common to use i for the index of a slice range (and k, v for map ranging), so to this looks more natural:

{{ range $i, $e :=  first 410 (.Data.Pages.ByDate.Reverse) }} 

Good to know.

Modbool and other modules functions are great to learn, so I’m glad you asked the question @Shiva, but empty divs are no bueno in your markup. Hate to be that guy, but I’d recommend using flex box (if you don’t need to support IE9) or add a clearfix mixin to use in the wrapping element. If you’re comfortable in sass, I’d recommend the implementation used by Bourbon:

http://bourbon.io/docs

Or here is some example CSS using a pseudoselector rather than an extra div:

.wrapper::after {
clear: both;
content: “”;
display: table;
}

@digitalcraftsman & @bep Thank so much, the modBool code works like a Boss. I also had to add some if conditions for the way I have my layout. Once I launch the site, I will share the link with you all.

@rdwatters How would I use the pseduoselector after every 3rd post? I am not sure I fully follow your recommendation.

Thanks!

@Shiva I guess I’d have to see what you’re trying to do, but with respect to the following:

This depends on your final markup, but pseudoselectors would help you here as well. So, for example, if you had a <ul> with 30 <li>'s, you could select every 3rd <li> with the following:


ul li:nth-child(3n + 3) {
//put your css rules in here
}

That said, if you have multiple <ul>'s each with exactly 3 <li>'s, you could do the following to just select the third item of each:


ul li:nth-child(3) {
//put your css rules in here
}

If you know there are going to be only three <li>'s in each <ul>, you could also use the :last-child:

ul li:last-child {
//put your css rules in here
}

Does that answer your question? Just shooting from the hip and taking a quick look at your sample templating up top, you could add another class to the opening div tag:

<div class="col-sm-4 myrow">

And then do something to the effect of:

div.col-sm-4.myrow:nth-child(3n + 3)::after {
clear: both;
content: "";
display: table;
}

Or you could do ...:nth-child(3)::after{... depending on what the parent markup looks like.
You’d have to test it , but hopefully this gets you on the right path. Cheers.

2 Likes

Thanks @rdwatters Wow, you pretty much nailed it without knowing a whole lot, and without me providing any code.

Yes, this is kind of what I am doing. It’s even simpler i.e. I have one parent bootstrap container <div> and within that, a series of <div class="post-box-detail article"> each of which contain the post title, image etc etc.

I will try out what you’ve suggested once I get my basic site up and running. I’ve been migrating this site for over a month now, need to launch soon.

Thank you!

So following up with a little bit more complex of a conditional, @bep

I’d like to sort all site pages by most recent publish date and and only grab the first 3 {{ first 3 range .Site.Pages.ByPublishDate.Reverse}} but I also only want the article if the section is equal to “tutorials” or “articles” {{if or (eq .Section "articles") (eq .Section "tutorials")}}. I’m having trouble combining these two conditions. Thoughts?

SOLVED

1 Like