Sign up (with export icon)

Media embed styles

Contribute to this guideShow the table of contents

The media embed styles feature lets you apply a style (for example, an alignment) to a media embed such as a YouTube or Vimeo video, a Spotify player, and so on. It is implemented by the MediaEmbedStyle plugin.

Out of the box the plugin ships five alignment styles. You can pick a subset of the built-ins, override their labels or icons, or register completely new styles through config.mediaEmbed.styles.

Installation

Copy link

The MediaEmbedStyle plugin is not loaded by default. Add it explicitly alongside MediaEmbed to enable the feature:

import { ClassicEditor, MediaEmbed, MediaEmbedStyle } from 'ckeditor5';

ClassicEditor
	.create( {
		attachTo: document.querySelector( '#editor' ),
		licenseKey: '<YOUR_LICENSE_KEY>', // Or 'GPL'.
		plugins: [ MediaEmbed, MediaEmbedStyle, /* ... */ ],
		toolbar: [ 'mediaEmbed', /* ... */ ]
	} )
	.then( /* ... */ )
	.catch( /* ... */ );
Copy code

Built-in styles

Copy link

The plugin provides the following five style options out of the box. Each option registers a toolbar button under the name mediaEmbed:<style-name> (used to place it in config.mediaEmbed.toolbar) and, for non-default styles, applies a CSS class to the media <figure> element. The default alignCenter option emits no class.

Block alignments – the media takes a full line, with surrounding text appearing above and below.

  • Left aligned media Left aligned – button mediaEmbed:alignBlockLeft, class media-style-block-align-left.
  • Centered media Centered – button mediaEmbed:alignCenter; default, no class.
  • Right aligned media Right aligned – button mediaEmbed:alignBlockRight, class media-style-block-align-right.

Wrap-text alignments – the media floats to one side and surrounding text wraps around it.

  • Left aligned media Left aligned – button mediaEmbed:alignLeft, class media-style-align-left.
  • Right aligned media Right aligned – button mediaEmbed:alignRight, class media-style-align-right.
Note

The actual styling of the media embeds is the job of the integrator. CKEditor 5 comes with some default styles, but they will only be applied to the media inside the editor. The integrator needs to style them appropriately on the target pages.

You can find the source of the default styles applied by the editor here: ckeditor5-media-embed/theme/mediaembedstyle.css.

Read more about styling the content of the editor.

The demo below shows the five built-in alignment styles, wired through the two compact split-button dropdowns and combined with the media embed resize feature. Select a figure and try the Wrap text and Break text dropdowns in its contextual toolbar – the action button reflects whichever alignment is currently applied.

Apollo 11 — July 1969

On the morning of July 16, 1969, a Saturn V rocket lifted off from Launch Complex 39A at Kennedy Space Center carrying three astronauts toward the Moon. Four days later, Neil Armstrong and Buzz Aldrin became the first humans to walk on another world while Michael Collins orbited overhead in the Command Module Columbia.

The footage above, restored by NASA from the original tapes, captured Armstrong's first step onto the Sea of Tranquility. The crew spent just under twenty-two hours on the surface and gathered 21.5 kilograms of rock and dust before splashing down in the Pacific on July 24, 1969 — fulfilling President Kennedy's pledge to land a man on the Moon and return him safely to the Earth before the decade was out.

Configuring the styles

Copy link

You can customize the set of available styles through config.mediaEmbed.styles. The configuration accepts an options array whose entries can be:

  • a string referencing a built-in style by name ('alignLeft', 'alignBlockLeft', 'alignCenter', 'alignBlockRight', 'alignRight'),
  • an object whose name matches a built-in (its fields are shallow-merged on top of the built-in),
  • an object with a new name (a fully custom style). See MediaStyleOptionDefinition for the required and optional fields.

When config.mediaEmbed.styles is not provided, all five built-in styles are available. This is the default behavior.

Picking a subset of built-in styles

Copy link

Pass only the styles you want to expose. Filtered-out styles disappear from the toolbar and cannot be applied through the 'mediaStyle' command.

mediaEmbed: {
    styles: {
        options: [ 'alignBlockLeft', 'alignCenter', 'alignBlockRight' ]
    }
}
Copy code

In the example above the wrap-text floats (alignLeft, alignRight) are dropped. The mediaEmbed:wrapText dropdown auto-skips because both of its items were filtered out, and only the three block alignments remain.

Overriding a built-in style

Copy link

To customize a built-in style, pass an object whose name matches the built-in plus the fields you want to change. Fields you set replace the built-in’s defaults. Fields you omit are inherited.

mediaEmbed: {
    styles: {
        options: [
            'alignLeft',
            { name: 'alignCenter', title: 'Center' },
            'alignRight'
        ]
    }
}
Copy code

Adding a custom style

Copy link

To add a custom style, supply an object with a fresh name, a title, an icon, and a className. You own the CSS for the resulting class. The plugin only writes the class to the figure when the style is applied.

import sideMediaIcon from 'path/to/side-media.svg';

ClassicEditor
    .create( {
        // ... Other configuration options ...
        mediaEmbed: {
            toolbar: [ 'mediaEmbed:alignCenter', 'mediaEmbed:side' ],
            styles: {
                options: [
                    'alignCenter',
                    {
                        name: 'side',
                        title: 'Side media',
                        icon: sideMediaIcon,
                        className: 'media-style-side'
                    }
                ]
            }
        }
    } );
Copy code
Note

The icon field accepts either a full SVG XML string (as shown above) or one of the short aliases shipped with the plugin: 'inlineLeft', 'left', 'center', 'right', 'inlineRight'.

/* Your CSS for the custom style. */
.ck-content .media.media-style-side {
    float: right;
    margin: 0 0 1em 1.5em;
    clear: none;
    box-shadow: 0 4px 16px rgba( 0, 0, 0, 0.2 );
}
Copy code

The same mechanism supports purely semantical styles. There is no requirement that a custom style be alignment-flavored.

To group several custom styles under a single split button in the toolbar, see Custom split-button dropdowns below.

Custom default style

Copy link

To mark a style as the default, set isDefault: true. Default styles do not need a className because the default state is encoded on the model as the absence of the mediaStyle attribute, so no class is written to the view. Applying a default style clears any other style that was previously set.

import naturalIcon from 'path/to/natural.svg';

mediaEmbed: {
    styles: {
        options: [
            'alignBlockLeft',
            {
                name: 'natural',
                title: 'Natural position',
                icon: naturalIcon,
                isDefault: true
            },
            'alignBlockRight'
        ]
    }
}
Copy code

Demo

Copy link

The demo below replaces the built-in alignments with three custom semantic styles – a Featured frame and two side asides grouped in a custom split-button dropdown. Select a figure to open the contextual toolbar.

Inside the International Space Station

Most footage of the International Space Station shows its exterior — solar arrays catching sunlight against the curve of the Earth. The walkthrough below takes a different route, moving through the interior module by module: the laboratories where experiments are run, the sleep stations the crew call home, and the equipment that keeps the station alive and working.

The station is a chain of interconnected pressurized modules contributed by the partner space agencies. Crew quarters, galleys, exercise gear, and dozens of experiment racks share the same volume; weightlessness turns every wall and ceiling into usable surface. Guided tours like this one are the closest most of us will get to seeing how seven people share a permanent home in orbit.

Toolbar configuration

Copy link

Each entry in config.mediaEmbed.toolbar is either a built-in component name (string) or an inline split-button dropdown definition (object). You can mix them freely.

Built-in dropdowns: mediaEmbed:wrapText groups the wrap-text alignments and mediaEmbed:breakText groups the block alignments. Each dropdown’s action button reflects whichever option from its group is currently applied to the selected media, falling back to the dropdown’s default (alignLeft for wrap, alignCenter for break) when none is applied. A dropdown is skipped automatically when fewer than two of its items survive your style configuration.

mediaEmbed: {
    toolbar: [ 'mediaEmbed:wrapText', 'mediaEmbed:breakText' ]
}
Copy code

Flat buttons: every style is also exposed as an individual button named mediaEmbed:<style-name>.

mediaEmbed: {
    toolbar: [
        'mediaEmbed:alignLeft', 'mediaEmbed:alignBlockLeft',
        'mediaEmbed:alignCenter',
        'mediaEmbed:alignBlockRight', 'mediaEmbed:alignRight'
    ]
}
Copy code

Custom split-button dropdowns: declare your own grouping inline, alongside built-in entries. The definition follows the MediaStyleDropdownDefinition shape – name, title, items, defaultItem – and all names use the full mediaEmbed: prefix.

mediaEmbed: {
    toolbar: [
        'mediaEmbed:alignCenter',
        {
            name: 'mediaEmbed:myAlignments',
            title: 'Alignment',
            items: [ 'mediaEmbed:alignBlockLeft', 'mediaEmbed:alignBlockRight' ],
            defaultItem: 'mediaEmbed:alignBlockLeft'
        }
    ]
}
Copy code

Custom dropdowns inherit the same item-filtering and skip behavior as the built-in dropdowns:

  • Items referencing styles that are not in the resolved config.mediaEmbed.styles.options list are filtered out at registration time. For custom dropdowns this also emits a console warning under media-style-configuration-definition-invalid so you know the config was not fully honored. Built-in dropdowns auto-skip silently.
  • A dropdown that ends up with fewer than two items is skipped entirely.
  • If the configured defaultItem was filtered out, the first surviving item becomes the new default.

A dropdown definition is also dropped (with the same warning) when its name lacks the mediaEmbed: prefix, items is empty or contains non-prefixed entries, defaultItem is not one of items, or title is empty.

Interaction with resizing

Copy link
Note

If you use the built-in alignment styles, you should combine them with the optional media embed resize feature as the two features were designed to be used together: resizing controls the width, alignment controls the position.

Without the resize feature, embeds span the full width of the editor by default and the alignment classes have no visible effect, because the figure already occupies the full row. Alignment starts producing a visible effect once the figure is narrower than its container (via the resize feature, your own CSS, or style preserved by other means).

Custom non-alignment styles (for example, a drop shadow or border treatment) do not depend on width and work regardless of whether resizing is enabled.

The HTML representation of an aligned and resized media embed looks like this:

<figure class="media media_resized media-style-align-left" style="width:50%;">...</figure>
Copy code

Common API

Copy link

The MediaEmbedStyle plugin registers:

  • A button for each style option, for example 'mediaEmbed:alignLeft' and 'mediaEmbed:alignCenter' (to use in the media embed contextual toolbar).

  • Two built-in split-button dropdowns: 'mediaEmbed:wrapText' and 'mediaEmbed:breakText'. Each is skipped automatically when fewer than two of its items survive your style configuration.

  • Any custom split-button dropdowns declared inline in config.mediaEmbed.toolbar.

  • The 'mediaStyle' command. It accepts a value matching one of the resolved configured options:

    // Float the selected media to the left so text wraps around it.
    editor.execute( 'mediaStyle', { value: 'alignLeft' } );
    
    // Clear the style to return to the default state.
    editor.execute( 'mediaStyle', { value: null } );
    
    Copy code

    Values outside the resolved options are silently rejected. Passing the effective default name (or null) always clears the attribute.

Note

We recommend using the official CKEditor 5 inspector for development and debugging. It will give you tons of useful information about the state of the editor such as internal data structures, selection, commands, and many more.

Contribute

Copy link

The source code of the feature is available on GitHub at https://github.com/ckeditor/ckeditor5/tree/master/packages/ckeditor5-media-embed.