How to Add Captions to Images in Drupal

Here's a recipe for adding (and formatting) captions to images in Drupal using Entity View Modes, File Entity, and Media 2.0

Design Goals

The objective is to allow a user to upload or select an image using the Media module, as well as choose a layout for the image. The media embed tags (non-HTML) placed into the body of the node/post will then be filtered by the media module, resulting in markup containing an image, surrounded by div elements with appropriate class attributes for position and styling. jQuery, or client-side JavaScript will not be required, and there will be a dedicated caption field. No other specialised 'captioning' or image modules will be required.

Requirements

You'll need all three of the above modules at their latest releases: Entity View Modes, File Entity, and Media 2.0

Setup

First we'll configure Entity View Modes - enter the configuration UI from either the Modules administration page, or from Configuration -> System -> Entity View Modes. We're going to create two new File View modes, so under the File View Mode section - click 'Add new view mode' and create a view named Story Image Left and Story Image Right. Enable both view modes for just the 'Image' file type. The file section of Entity View modes should now look like this...

Now we'll configure a story image style. The assumption we're making here is that these images (one or more) are going to appear in a story, or article, and that they will follow a house style for the publication. In this case we're going to say that all of our embedded story images will have a maximum width of 400px. Let's go to the Image Style configuration UI, Configuration -> Media -> Image Styles and create a 'story' image style, with a Scale effect  - which will look like this...

 

Okay - we've laid the ground work. Now we'll switch over to the File Entity admin UI and add our Caption field to the Image file type. Let's go to Structure -> File Types, and edit the Image file type. Add the caption field and choose Text and Text field for the field and widget types. Your image type field display should look like this...

Now let's configure the display settings for our Image file type. On the 'Manage Display' tab, you'll see your two new custom file entity views - Story Image Left and Story Image Right. Configure them both as follows:

Now let's move over to the Manage file display tab and again, configure both Story Image Left and Story Image Right as follows (be sure to select just the Image type, as well as choose the 'story' image style we created earlier):

 

For the image 'embedding' part of this recipe - we should be just about ready to go - with one caveat. You'll need to be sure that the Media browser icon is available to the WYSIWYG editor in use. I'm using the WYSIWYG Drupal module, and I've added the Media browser icon to my Filtered HTML content profile - which is currently set to use CKEditor 3.6.5.7647 (I'm not sure that the WYSIWYG module supports v4 of the CKEditor yet - hence 3.6.5.7647). We're ready to create our story.

Make It So...

Create a new content item (Basic Page or whatever), place some text in the body of your post - enough text so that we can see how we can force the image to align either right, or left along with a caption below the image. Then click on the Media browser icon and upload (or choose) an image. If you're uploading an image for the first time - you'll have a chance to fill in the Caption field. Otherwise you can add the caption before you embed the image using the Content -> File UI. Assuming you've got an image, with a populated caption field, go ahead and click on the Media browser icon, choose your image, and most importantly - just before you embed it - set the current format of the embedded image to either the Story Image Left, or Story Image Right view mode. The screen below will appear as the second step in the embed process.

And we're done - we'll, almost. What we need now is a little CSS magic to align the image and format the caption. In the editor window, the Media browser will have placed a media embed tag into the body of your content that will look something like this

[{"fid":"15","view_mode":"story_image_left","type":"media","attributes":{"height":"267","width":"400","alt":"Cooking","title":"More Cooking","class":"media-element file-story-image-left"}}] 

When the post or page is viewed from a client browser - the tags above will be replaced with something like this:

<div class="media media-element-container media-story_image_left"><img alt="Cooking" class="media-element file-story-image-left" height="267" src="/sites/default/files/styles/story/public/DSC00266.jpg?itok=675XxS2z" style="line-height: 1.5;" title="More Cooking" typeof="foaf:Image" width="400" />
<div class="field field-name-field-caption field-type-text field-label-hidden">
<div class="field-items">
<div class="field-item even">An example of how a caption can be added using the new File Entity type.</div>

The important thing to note here, is that as of the latest release of the Media module, a CSS class attribute will be placed in the surrounding div, indicating which view mode we have chosen. This gives us the ability to style both the image and caption to our liking. For example, for the Story Image Left (which - if you'll remember, is following a house style of 400px width) I've used the following CSS:

.media-story_image_left, .media-story_image_right {
  width: 410px;
  margin-bottom: 2px;
}
.media-story_image_left { float: left; }
.media-story_image_right { float: right; }
.media-story_image_left .field-name-field-caption, .media-story_image_right .field-name-field-caption {
  font-size: 12px;
}
.media-story_image_right .field-name-field-caption {
  margin-left: 10px;
}
.file-story-image-left {
  float: left;
  margin-top: 5px;
  margin-right: 10px;
}
.file-story-image-right {
  float: right;
  margin-top: 5px;
  margin-left: 10px;
}

The Big Reveal

The result of all of the above? Well it should look something like this...

For module developers, there is also a hook in the Media module that will let you decide which elements you'd like to use to surround the image and caption hook_media_token_to_markup_alter. And of course there are other strategies and modules for captioning images in Drupal - although few that let site builders decide for themselves how captioned images should be implemented. There is also a philosophical choice about where you think the caption data (and other data for your files) belongs, and whether you want to hand this over to Drupal fields, or keep the caption in the content of your post using some other WYSIWYG plugin, or insertion module, but I think the method above is okay. Would be interested to know what other Drupalers out there think, and hope that some of what's here is helpful in general.

Category

Comments

Excellent write up and great uses of screens and examples to illustrate. The tricky aspect of the this recipe is understanding how file view modes connect back to image styles. Great job making that clear.

Up to now, I've been using the Insert module with an "inline_images" field to allow an editor to insert inline images with styles, but this leaves out captions. WYSIWYG + Media is a more elegant, complete solution, albeit with some extra configuration overhead. I'm looking forward to trying this out.

Hi Anthony,
great post!!! I am trying to do it the same way - but caption is never displayed (even not included in the media embed tag). I am using current dev-releases of media (7.x-2.x-dev - 2015-Oct-01) and the additional field is not included when using wysiwyg media embed button.

Thank you for this post.
I tried to do the same but I've the same problem Kai has with the 7.x-2.0-beta1 media release. Did you find any solution ?

I had this issue, too. Check the Text format you're using: Convert Media tags to Markup should be checked and listed 1st under Filter processing order.

I've been trying to use this tutorial in D8 and I must say I'm stumped. The instruction "Enable both view modes for just the 'Image' file type." Doesn't seem to apply anymore and I don't get a "Manage file display" tab later on.

Did anyone manage to make this work under D8?

Is there an updated version of this tutorial for Drupal 8?
The File Entity module doesn't seem to work in the same way anymore and will be deprecated soon.