I know I'm late to the game but I found what I feel is a fairly elegant solution that doesn't feel hacky.
With for
loop's limit
and offset
params, we can iterate one row at a time, N posts per row.
First, we count the number of rows we'll need to enumerate over:
{% assign rows = site.posts.size | divided_by: 2.0 | ceil %}
The Ruby equivalent would be rows = (posts.size / 2.0).ceil
(odd numbers get their own row).
Next, we'll iterate over the rows:
{% for i in (1..rows) %}
<div>
Now we need to calculate the collection offset with (i - 1) * 2
(using forloop.index0
):
{% assign offset = forloop.index0 | times: 2 %}
Then we can iterate over the slice of posts starting at the row's offset (equivalent to posts[offset, 2]
in Ruby):
{% for post in site.posts limit:2 offset:offset %}
<a href="{{ post.url }}">{{ post.title }}</a>
{% endfor %}
Close the row div
element and for loop:
</div>
{% endfor %}
That's it!
In Ruby, this would be:
rows = (posts.size / 2.0).ceil # the number of rows
(1..rows).each do |i|
offset = (i - 1) * 2
# <div>
posts[offset, 2].each do |post|
# <a href="#{post.url}>#{post.title}</a>
end
# </div>
end
All together now, in Liquid:
{% assign rows = site.posts.size | divided_by: 2.0 | ceil %}
{% for i in (1..rows) %}
{% assign offset = forloop.index0 | times: 2 %}
<div>
{% for post in site.posts limit:2 offset:offset %}
<a href="{{ post.url }}">{{ post.title }}</a>
{% endfor %}
</div>
{% endfor %}
Hope this helps someone!