0

I have this loop:

<?php
$categories = get_terms('my_category');
foreach ( $categories as $category ) :
?>

I want to split the posts into 4 separate div columns so that post titles will be alphabetical vertically like:

a | d | g | j
b | e | h | k
c | f | i | l

How do you get the total post count and divide evenly into fourths?

Edit: Here is the whole loop I'm working with

<?php
$categories = get_terms('archive_category');
foreach ( $categories as $category ) :
?>
<div>
<a data-toggle="collapse" href="#<?php echo $category->slug; ?>"><h3><?php echo $count; ?><?php echo $category->name; ?></h3></a>
<div class="collapse" id="<?php echo $category->slug; ?>">
<?php
$posts = get_posts(array(
'post_type'  => array('custom_post', 'custom_post', 'custom_post'),
'taxonomy' => $category->taxonomy,
'term'  => $category->slug,
'numberposts' => -1,
'orderby'=>'title',
'order'=>'ASC'
));

foreach($posts as $post) :
setup_postdata($post); 
?>

<a href="<?php the_permalink(); ?>"><?php echo get_the_title( $p->ID ); ?></a>

<?php endforeach; ?>
</div>
</div>
<?php endforeach; ?>
  • get_terms() won't get you the posts; it'll get the terms in a given taxonomy. Is that what you're trying to do? – Pat J Jan 30 at 17:28
  • Yes, I am getting the name of the category and then outputting all the posts within the category underneath the category header. – semory Jan 30 at 17:47
  • You could achieve that layout with just CSS flexbox – RiddleMeThis Jan 30 at 17:57
  • I don't think there is a css solution to this. I tried column-count but the layout shifts when I expand content ( the links show when the category header is clicked). – semory Jan 30 at 18:01
1

I had a similar problem couple years ago. Here's a gist I've published, which shows the basic idea how I solved the problem,https://gist.github.com/koskinenaa/4d8461116885c0e64d5ca167ae53434d

Applying the gist to your situation I think the solution could be something like this. I didn't test this so it might require some tweaking, but it should at least point you to the right direction. Of course you need to add relevant css for the ul elements to position them next to each other.

In my example I moved the term and post queries to their own helper functions, but this is just a matter of preference.

function archive_categories( string $tax ) {
  $categories = get_terms($tax);
  return ( $categories && is_array($categories) ) ? $categories: array();
}

function archive_category_posts_query( string $tax, string $term ) {
  $args = array(
    'post_type'   => array('custom_post', 'custom_post', 'custom_post'),
    'numberposts' => -1,
    'orderby'     => 'title',
    'order'       => 'ASC'
    'tax_query' => array(
      array(
          'taxonomy' => $tax,
          'field'    => 'slug',
          'terms'    => $term,
      ),
    ),
  );
  return new WP_Query($args);
}

$categories = archive_categories('archive_category');
$col_count = 4;

foreach ($categories as $category) :
  $category_posts_query = archive_category_posts_query($category->taxonomy, $category->slug);
  $post_count = $category_posts_query->found_posts;
  $posts_per_col = ceil( $post_count / $col_count );
  $i = 0;
  ?>
  <div>
    <a data-toggle="collapse" href="#<?php echo $category->slug; ?>">
      <h3><?php echo $count; ?><?php echo $category->name; ?></h3>
    </a>
    <div class="collapse" id="<?php echo $category->slug; ?>">
      <ul>
        <?php foreach ( $category_posts_query->posts as $category_post ) : 
          if ( $posts_per_col === $i ) {
            $i = 0; 
            echo '</ul><ul>';
          }
        ?>
          <li>
            <a href="<?php esc_url( get_the_permalink( $category_post->ID ) ); ?>"><?php echo esc_html( $category_post->post_title ); ?></a>
          </li>
        <?php $i++; endforeach; ?>
      </ul>
    </div> <!-- collapse -->
  </div> <!-- collapse wrapper -->
<?php endforeach;

EDIT 5.2.2020

Categories into columns? You mean something like this?

$categories = archive_categories('archive_category');
$category_count = count( $categories );
$col_count = 3;
$categories_per_col = $category_count > $col_count ? ceil( $category_count / $col_count ) : 1;
$column_index = 1;

echo '<div class="row">';
foreach ($categories as $category) :
  $category_posts_query = archive_category_posts_query($category->taxonomy, $category->slug);
  if ( $column_index > $col_count ) {
    $column_index = 1;
    echo '</div><div class="row">';
  }
  $classes = array(
    'column_1_of_' . $col_count,
    'column-' . $column_index,
  );
  ?>
  <div class="<?php echo implode( ' ', $classes ); ?>">
    <a data-toggle="collapse" href="#<?php echo $category->slug; ?>">
      <h3><?php echo $category->count . ' ' . $category->name; ?></h3>
    </a>
    <div class="collapse" id="<?php echo $category->slug; ?>">
      <ul>
        <?php foreach ( $category_posts_query->posts as $category_post ) : ?>
          <li>
            <a href="<?php esc_url( get_the_permalink( $category_post->ID ) ); ?>"><?php echo esc_html( $category_post->post_title ); ?></a>
          </li>
        <?php endforeach; ?>
      </ul>
    </div> <!-- collapse -->
  </div> <!-- collapse wrapper -->
<?php $column_index++; endforeach;
echo '</div>';
| improve this answer | |
  • Thanks! This is really close, but isn't quite what is needed in this instance. I made an edit to the code above which I hope shows what I am going for. Basically instead of being based on post_count it needs to be based on a category count. The category title is listed and then posts within the category are listed below. So categories need to spit into thirds rather than posts. Any help appreciated! – semory Feb 4 at 18:52
  • @semory So the categories should be the columns and posts just plain lists, right? I added another code example to my answer. Is that what you're after? – Antti Koskinen Feb 5 at 10:23
  • Thanks again! I was able to modify your last code sample to get what I needed. – semory Feb 5 at 20:51
0

The answer is CSS and you've got a couple options!

<?php $categories = get_terms('my_category'); ?>

<ul>
    <?php foreach ( $categories as $index => $category ): ?>
        <li>
            <a href="<?php the_permalink(); ?>"><?php echo get_the_title( $p->ID ); ?></a>
        </li>
    <?php endforeach; ?>
</ul>

You can use Flexbox...

ul {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  height: 306px;
  width: 200px;
}
li {
  width: 100px;
  height: 100px;
}

OR, you can use Text Columns

ul {
  column-count: 2;
  column-gap: 0;
}
li {
  display: inline-block;
}

Here's a great resource with further details and codepens.

| improve this answer | |
  • Thanks. These css solutions don't quite work. I can't use css3 columns because the layout shifts when content is expanded. The category header expands the the list of posts. flexbox doesn't work with 4 columns. I messed with it for a while. – semory Jan 30 at 19:47
  • If you can replicate your code in a codepen I'll fix it for you – Waldo Rabie Jan 30 at 19:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.