N per row with Thymeleaf

Recently I worked on an spring application that used the Thymeleaf template library to render HTML. The specific problem I faced was how to render an arbitrarily long list of items in a raster scanned manner with a given number of columns. So, for example, if the items were US cities and the column width was 5 I wanted to see something like this:

Here’s my template:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head lang="en">
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>Major US Cities</title>
    <link href='https://fonts.googleapis.com/css?family=Montserrat' rel='stylesheet' type='text/css' />
    	body {
    		font-family: 'Montserrat', sans-serif;
    	table {
    		border-collapse: collapse;
    		font-size: 150%;
    	td {
			width: 200px;
			height: 50px;
			text-align: center;
			vertical-align: middle;
		tr:nth-child(odd) {
			background-color: #ccc;

	<h1>Major US Cities</h1>

		<tr th:each="city : ${cities}" th:if="${cityStat.index % width == 0}">
			<td th:each="index : ${#numbers.sequence(cityStat.index, cityStat.index + width - 1)}"
				th:if="${index lt cityStat.size}"



The money portion starts at line 33 with the th:each iteration attribute. This template is driven by a spring controller that sets the cities and width parameters.

package com.gosynaptic.controller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

public class ExampleController {
	private List<String> cities() throws IOException {
		List<String> list = new ArrayList<>();	
		try (BufferedReader br = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("cities.txt"), "UTF-8"))) {
			String line;
			while ((line = br.readLine()) != null) {
		return list;
	@RequestMapping(value="/table", method={RequestMethod.GET, RequestMethod.POST})
	public ModelAndView table() throws IOException {
		ModelAndView mav = new ModelAndView("/cities");
		mav.addObject("cities", cities());
		mav.addObject("width", 5);
		return mav;


If you have a better solution please post it in the comments! I’m making the minimal spring boot project available here for your convenience.

Posted in Technical | Comments Off