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.