You can do it like so:
// Group the categories by their FIRST LETTER.
$groups = [];
foreach ( $category_list as &$term ) {
$letter = strtoupper( substr( $term->name, 0, 1 ) );
if ( ! isset( $groups[ $letter ] ) ) {
$groups[ $letter ] = [];
}
$groups[ $letter ][] = $term;
}
// Now display them, three groups in each row.
echo '<div class="row">';
$i = 0;
$letters = array_keys( $groups );
foreach ( $groups as $letter => $terms ) {
$new_row = ( $i % 3 === 0 );
if ( $i && $new_row ) {
echo '</div><div class="row">';
}
// Show either "A - C", "A & B", or just a letter.
if ( ! $i || $new_row ) {
$range = array_slice( $letters, $i, 3 );
if ( $end = $range[ count( $range ) - 1 ] ) {
$sign = ( count( $range ) > 2 ) ? ' - ' : ' & ';
$range = $letter . $sign . $end;
echo '<h2 class="col-12">' . $range . '</h2>';
} else {
echo '<h2 class="col-12">' . $letter . '</h2>';
}
}
echo '<div class="col-sm">';
if ( ! empty( $terms ) ) {
echo '<ul>';
foreach ( $terms as $term ) {
echo '<li>' . $term->name . '</li>';
}
echo '</ul>';
}
echo '</div>';
$i++;
}
echo '</div>';
The output would look like so:
UPDATE
So this is the proper version, based on the layout on Carryology.com/brands/
(as of writing).
I have commented the code (although not all parts) and it shouldn’t be hard for you to make modifications to the code:
// Group the categories by their FIRST LETTER.
$letters = range( 'A', 'Z' );
$groups = [];
foreach ( $category_list as &$term ) {
$letter = strtoupper( substr( $term->name, 0, 1 ) );
if ( ! isset( $groups[ $letter ] ) ) {
$groups[ $letter ] = [];
}
$groups[ $letter ][] = $term;
}
$cols = 3; // number of letters in a range
for ( $i = 0; $i < count( $letters ); $i++ ) {
if ( $i % $cols === 0 ) {
$list = array_slice( $letters, $i, $cols );
// Start the row.
echo '<div class="row">';
// Show the heading. (letter range)
$end = $list[ count( $list ) - 1 ];
$sign = ( count( $list ) > 2 ) ? ' - ' : ' & ';
$range = $end ? $sign . $end : '';
// Show either "A - C", "A & B", or just a letter.
echo '<h3 class="col-sm-2">' . $list[0] . $range . '</h3>';
// Put all the letter terms in a single group.
$groups2 = [];
for ( $j = 0; $j < count( $list ); $j++ ) {
if ( isset( $groups[ $list[ $j ] ] ) ) {
$groups2 = array_merge( $groups2, $groups[ $list[ $j ] ] );
}
}
$cols2 = 5; // number of columns in a row, excluding the heading.
$n = count( $groups2 );
$rows = floor( $n / $cols2 );
$diff = $n - $rows * $cols2;
for ( $k = 0, $l = 0; $k < $cols2; $k++ ) {
$x = $diff ? 1 : 0;
// Start a column.
echo '<ul class="col-xs-4 col-sm-2">';
// Show the group terms.
foreach ( array_slice( $groups2, $l, $rows + $x ) as $term ) {
echo '<li>' . $term->name . '</li>';
$l++;
}
$diff = $diff ? $diff - 1 : 0;
// Column end.
echo '</ul>';
}
// Row end.
echo '</div>';
}
}
The output would look like so: