Medium-like Posts for WordPress
Although the single-column full-width style has been around for a while, I think Medium popularised it by putting it out there in a distraction-free manner. There’s few features on the surface and no clutter hampering the content. Because of its simplicity, it isn’t very opinionated and works well for many people (such in the case of Medium, where everyone is “restricted” to the same design).
The key idea behind this sort of design is that it (hopefully) provides a superior reading experience, whereby there’s nothing else standing between the reader and the core content. The design continually leads you into the content, and freely uses the space it has been been granted.
Within WordPress however, we’ve come to recognise a particular style. We often see two columns (content + sidebar) as well as a footer area that has three or four columns for widgets. Even today, default themes are still being shipped with a template component called sidebar.php
. This sort of wording sets the wrong expectations.
With our single column approach, instead of having something along the lines of:
.col-content { width: 800px; // or % width, flex, etc. }
We now simply declare nothing at all. The parent container for content simply spans across the entire page. In turn, the child elements (text, images, media, etc.) that make up the content, now have to take on additional properties.
Handling Content
My posts are predominantly made up of text, but it likely isn’t wise to let text stretch like that on larger displays. There are countless articles on the topic, but you’ll generally find that they call for 50 to 75 characters per line. With our new found freedom, this means we’ll need to dial it in and control it. As there are a fair amount of textual elements (more than my other elements), we can tighten them up using something along the lines of:
.entry-content > * { max-width: 800px; margin-left: auto; margin-right: auto; }
Using the direct descender with a universal selector enables us to set a foundation, but at the same time easily allows anything to change with a bit more specificity, for instance .entry-content > blockquote
.
Handling Images
Using the above example, all images will also be limited in width. But what if we wanted to create a full-width image? We could use the full size image format to help target the images we want to show at full width:
.entry-content > img.size-full { max-width: 100% }
There’s only one problem with that, WordPress by default encapsulates images with a Paragraph selector. In my opinion, it doesn’t make sense to have images inside of a paragraph unless they’re providing some form of inline value.
With that in mind, we can remove the P tags in a non-destructive manner using a filter (via CSS-Tricks):
function filter_ptags_on_images( $content ){ return preg_replace( '/<p>\s*(<a .*>)?\s*(<img .* \/>)\s*(<\/a>)?\s*<\/p>/iU', '\1\2\3', $content ); } add_filter( 'the_content' , 'filter_ptags_on_images' );
This means we get a nice result like this now:
We’re not quite in the clear yet, as adding a link or caption (or both) adds additional elements around the image. Unfortunately, via WordPress you can’t specifically target those parent wrappers, nor can you go upstream with CSS (yet). So there’s no way to tell a link apart for example.
To assist us, we should add a class on the parent called wp-image-parent as well as bubble up any additional classes you desire. This allows us to make the same statement as before, but to also account for various image options.
.entry-content > .wp-image-parent.size-full { max-width: 100% }
It’s not the best of solutions as it causes a reflow, but here’s the jQuery I’ve thrown in:
$( 'a, .wp-caption', '.entry-content' ).each( function( i, e ) { if ( $( this ).find( 'img' ).length !== 0 ) { $imgClasses = $( 'img', this ).attr( 'class' ); $( this ).addClass( 'wp-image-parent ' + $imgClasses ); } });
This enables us now to target captions too, like the image below:
I’ve been doing all this as part of my own sites redesign, so I’m still working through everything. The code could be cleaner and better organised, but I hope you’re able to understand the idea I’m pursuing and how I’m getting there. Feedback and thoughts welcome.