Vertical alphabetically post columns

EDIT

From the comments from the OP

There’s a few concerns though and suggestions on improvement. First of all, not sure if i missed something, but the list are not links? Second is that with this list it outputs a letter even though it doesn’t have a post assigned to the letter…..

and

Posts that starts with an number won’t be listed, would it be possible to extend the range for this?

I have totally rewritten the entire code. Still, both blocks of codes in your question had major issues, so again, I’ve dropped both. As well as @birgire indicated, the code in my original answer had the drawback of the amount of db queries due the fact that I was including empty letters as well (thought this is what you wanted)

I have made the links clickable, as well as made provision to include numbers as the first character to sort by. What I did not go into detail in is styling.

So here are the revised code

<?php 
$args=array(
    'post_type' => 'portfolio',
    'portfolio-category' => 'indie',
    'orderby' => 'title',
    'order' => 'ASC',
    'posts_per_page'=>-1,
    'ignore_sticky_posts'=>1
);

$my_query = new WP_Query($args);
$q = array();
if( $my_query->have_posts() ) {
    while ($my_query->have_posts()) {
        $my_query->the_post(); 

            $t="<a href="". get_permalink() .'" rel="bookmark" title="Permanent Link to '. get_the_title() .'">' . get_the_title() .'</a>';
            $c = strtoupper(substr(get_the_title(),0,1)); 
            $q[$c][] = $t;
    }
} 
wp_reset_postdata();  // Restore global post data stomped by the_post(). 

$count = 0;

foreach ($q as $key=>$values) {
    $count++; ?>

    <div class="column<?php echo $count; ?>" style="width:9%; margin-right:2%; float:left; margin-bottom:25px">

        <?php echo $key;

        foreach ($values as $value) { ?>    
            <div style="width:95%; padding-right:5%">
                <p>
                    <?php echo $value; ?>
                </p>
            </div>
        <?php } ?>

    </div>

    <?php if( 0 == $count%9 ){ ?>

        <div class="clear" style="clear:left"></div>

    <?php } 
}

Here is the output from the code above

enter image description here

WHAT YOU NEED TO DO

  • Scrap everything from the original answer. I’m keeping the original answer for the sake of its completeness and that it might become useful to someone else in future.

  • Add your own styling and style according to your needs

  • Make any modification to suite your own personal needs

I have given you the backbone to accomplish your needs. I would expect that this would take to at least 99% in achieving your goal. Please let me know on your progress

ORIGINAL ANSWER

I’ve went a took a different route that what you took in your examples. Here is what I did and how it works:

STEP 1

@birgire did this post a while ago about extending the WP_Query class which enables you to retrieve a post by first letter. Is is done with the introduction of a new parameter, name__like. I’ve used this to create the custom query. Here is the new class

/**
 * Class WPSE_Query
 *
 * Add a support for the name__like parameter
 *
 * @link https://wordpress.stackexchange.com/a/136758/26350
 *
 */
class WPSE_Query extends WP_Query 
{       
    public function __construct( $args = array() )
    {
        add_filter( 'posts_where', array( $this, 'posts_where' ), 10, 2 );
        parent::__construct( $args );
    }
    public function posts_where( $where, $qry )
    {       
        remove_filter( current_filter(), array( $this, __FUNCTION__ ) );    
        $name__like = $qry->get( 'name__like' ); 
        if( ! empty( $name__like )  )
        {
            $where .= " AND ";
            $where .= $GLOBALS['wpdb']->posts;
            $where .= ".post_name LIKE '";
            $where .= esc_sql( like_escape( $name__like ) );
            $where .= "%' ";            
        }   
        return $where;
    }
}

This goes into your functions.php.

STEP 2

To dynamically retrieve a list of all letters of the alphabet, I’ve used the php function range() and assigned a variable to it.

$range = range('A','Z');

STEP 3

I’ve then passed my variable through a foreach loop to get all the individual letters, which is passed to my custom query

foreach ($range as $r){ }

STEP 4

Instead of using WP_Query, I’ve now used the new class that was created in STEP 1 called WPSE_Query. I also used the new parameter name__like and passed each letter of the alphabet to it to retrieve my posts accordingly

$args = array(
            'post_type'             => 'portfolio',
            'orderby'               => 'title',
            'order'                 => 'ASC',
            'posts_per_page'        => -1,
            'portfolio-category'    => 'indie',
            'ignore_sticky_posts'   => 1,
            'name__like'            => $r
        );

        // The Query
        $the_query = new WPSE_Query( $args ); 

The reason why I went through all this trouble is to give me more control over the HTML

STEP 5

I’ve introduced a counter to control when HTML elements are introduced and how they are advanced

STEP 6

To create and style the columns, I have used the following line. Note: I’ve used inline styles here just to showcase the output. You should add these styles to your stylesheet rather than keeping them as inline styles

<div class="column<?php echo $count; ?>" style="width:9%; margin-right:2%; float:left; margin-bottom:25px">

As you can see, I have used the counter here to advance my column class by one on each iteration

STEP 7

Finally, to stop any wacky output, you need to clear the float after every ninth post. With the use of the counter and the modulus division operator, a clear float is inserted after every ninth post

if( 0 == $count%9 ){ ?>

        <div class="clear" style="clear:left"></div>

    <?php }

ALL TOGETHER NOW!

This is the final code:

<?php
$count = 0;
$range = range('A','Z');

foreach ($range as $r){
   $count++;

?>

    <div class="column<?php echo $count; ?>" style="width:9%; margin-right:2%; float:left; margin-bottom:25px">

<?php

        echo '<p>' .$r . '</p>';

        // $args for the custom query
        $args = array(
            'post_type'             => 'portfolio',
            'orderby'               => 'title',
            'order'                 => 'ASC',
            'posts_per_page'        => -1,
            'portfolio-category'    => 'indie',
            'ignore_sticky_posts'   => 1,
            'name__like'            => $r
        );

        // The Query
        $the_query = new WPSE_Query( $args );  

        // The Loop
        if ( $the_query->have_posts() ) {
            while ( $the_query->have_posts() ) {
                $the_query->the_post();

                    ?>

                        <div style="width:95%; padding-right:5%">
                            <p>
                                <?php the_title(); ?>
                            </p>
                        </div>

                    <?php

            }
        } 

        wp_reset_postdata(); ?>

    </div>

<?php

    if( 0 == $count%9 ){ ?>

        <div class="clear" style="clear:left"></div>

    <?php }
}

?>

All you need to do is to tweak and add all relevant HTML mark-up

Here is the output from the code above

enter image description here

and here is the HTML structure

enter image description here