One of my main goals when building a new site is to make adding content as intuitive as possible. The biggest challenge in this regard is often image selection by content editors. The quality of images used on a site comes down to a mixture of the content editor’s experience selecting and resizing images, their available time and access to good quality images in the first place. In an ideal world I will have anticipated these scenarios and my code will make the best of displaying images dependent on the input.
In NationBuilder this is what I’ve been playing around with in regard to blog featured images (as always, it’s a work in progress and I’m open to any suggestions)…
There are two obvious places we can pull our featured image from:
- The social media meta image
- The file upload section
I think in an ideal situation the social media meta image makes the most sense for our featured image. It’s good practice for content editors to add this image in case the post is shared. Twitter’s ideal post size image is 1600 x 900 pixels and Facebook’s is 1200 x 630 pixels, which ratio wise are very close (the facebook height to width ratio is slightly less), so if you can add an image using Twitter’s aspect ratio it will do the job for both platforms and if our featured image is styled to this aspect ratio as well it will kill three birds with one stone.
However, this requires the image to be resized correctly. There are plenty of tools online that will help with this, so in theory it’s not hard, but it is an extra step in a process to add content that some editors will either ignore or simply (often for good reason) not have time for.
Nonetheless, in most cases this is our best case scenario. So we’ll include it in our blog post summary code:
{% if page.has_meta_image? %} <div class="featured-image" style=“background-image:url({{ page.meta_image_url }});”></div> {% else %} <div class="featured-image" style=“background-image:url(default_featured_image.jpg);”></div> {% endif %}
In the above code I’ve done the following:
- Performed a check to see if there is a social media meta image associated with this post ({% if page.has_meta_image? %}).
- If so, added in our ‘featured-image’ div with the social media meta image added as a background image.
- if not, added in our ‘featured-image’ div with a default image (default_featured_image.jpg) for our background image.
Then in our css we want to add the following:
.featured-image { padding-bottom: 56.25%; background-size:cover; background-position:center; }
Here we’re assuming that our ‘featured-image’ div is contained in a wrapper that limits its maximum width to an appropriate size. The image’s width will be 100% of whatever that container is. In relation the height is defined by adding bottom padding at 56.25%. 100% : 56.25% translates to the same aspect ratio as a Twitter card.
We’re then applying a ‘background-size:cover’ attribute so that our background image fits the space as well as possible without any gaps and a ‘background-position:center’ attribute to center the image vertically and horizontally in the available space.
In many ways this is a good place to finish. It gives the editor the option to add an appropriate featured image to the post, it encourages best practice for social media sharing by using that image in both scenarios and it has a fallback option for instances when best practice is not followed.
However this still leaves us in a scenario where the site can end up looking shoddy. The editor may not resize images so they could be the wrong aspect ratio or too small. They might also upload images that have text on them (e.g. flyers for an event), which look really bad when fitted to our fixed aspect ratio featured image space!
With all these things in mind I started to think about how we can give the user some more intuitive options for adding images that make the best of whatever they have at their disposal.
This is where the files section of the post or page comes into play. Perhaps we can look for our featured image there instead. Trouble is, what if there are multiple uploads in this section? We need some way of identifying which upload is our featured image. The simplest way I can think of is to look for a signifier in the name of the file.
For example, let’s say our featured image is called ‘featured_post_image.jpg’, we could look through all our file uploads and find any image that has the substring ‘featured’:
{% for attachment in page.attachments %} {% if attachment.file_name contains 'featured' %} <div class="featured-image" style=“background-image:url({{ attachment.url }});”></div> {% break %} {% endif %} {% endfor %}
Here we are:
- Looking through all the uploads in the files section of our post (page.attachments)
- If any of them have a filename that contains the substring ‘featured’ we’re going to output that as our featured image.
- Finally, adding a {% break %} tag after that output to stop the loop from continuing after that point.
So the next thing I want to do is provide a fallback to our social media image in instances where there is no image containing ‘featured’ in our files section…
{% assign hasFeaturedAttachment = false %}
{% for attachment in page.attachments %} {% if attachment.file_name contains 'featured' %} <div class="featured-image" style=“background-image:url({{ attachment.url }});”></div> {% assign hasFeaturedAttachment = true %} {% break %} {% endif %} {% endfor %}
{% if hasFeaturedAttachment == false and page.has_meta_image? %} <div class="featured-image" style=“background-image:url({{ page.meta_image_url }});”></div> {% elsif hasFeaturedAttachment == false %} <div class="featured-image" style=“background-image:url(default_featured_image.jpg);”></div> {% endif %}
Here we are:
- Creating a variable called ‘hasFeaturedImage’ and setting it to false.
- Then looking for our featured image in the files section
- Changing this ‘‘hasFeaturedImage’ variable to true if it exists.
- Then we’re outputting our social media image but ONLY if the ‘hasFeaturedAttachment’ variable is still false AND we actually have a social media image.
- Finally, if there is no social media image either we’ll output our default image.
However if we’re just going to add the image but use it as a covered background image in the same way as our social media image there’s not much point. We still face the same problem if the image is not sized correctly. I want the client to use this method to upload featured image that are not particularly well optimised for the space.
Let’s say they are adding an event and the only image at their disposal is a portrait flyer for that event. If we drop that in using either method above we’re only going to see the middle section of the flyer which will probably show some random, partially cropped, typography. I see this a lot and it always looks terrible. I want a way to avoid this without me having to curate these images for the client.
With that in mind I’m going to use the file upload option as a way to display this sort of content as best we can by giving the image a percentage size of the featured image space rather than covering it.
The first thing I’m going to do is to add the image within a positioned img tag instead of as a background image. This is not strictly necessary for what we’ve just discussed, but it will give us more options for display going forward (as I’ll explain later) so I think it’s worth doing.
So now the code for inserting the file uploaded image looks like this:
{% assign hasFeaturedAttachment = false %} {% for attachment in page.attachments %} {% if attachment.file_name contains 'featured' %} <div class="featured-image"> <div class="positioner"> <img src="{{ attachment.url }}"/> </div> </div> {% assign hasFeaturedAttachment = true %} {% break %} {% endif %} {% endfor %}
With the css for positioning our image in the center of the available space like this:
.featured-image {
padding-bottom: 56.25%;
background-size:cover;
background-position:center;
position: relative;
background-color:#ccc
}
.positioner {
position:absolute;
width:100%;
height:100%;
display:flex;
align-items:center;
justify-content: center;
overflow:hidden;
}
.positioner img {
min-height:85%;
min-width:85%;
}
This gives us something that looks like this:
Next I started to think about how we could take this a step further and optimise display for different types of image but that’s one for another post.
Leave a Reply