MJML component for creating interactive image carousels in email templates with thumbnail navigation and cross-client compatibility
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
MJML Carousel provides interactive image carousel components for email templates. It uses CSS-only interactivity with radio buttons and selectors to create cross-client compatible carousels with thumbnail navigation, hover effects, and click-through functionality.
npm install mjml-carouselimport { Carousel, CarouselImage } from "mjml-carousel";For CommonJS:
const { Carousel, CarouselImage } = require("mjml-carousel");<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-carousel>
<mj-carousel-image src="https://example.com/image1.jpg" />
<mj-carousel-image src="https://example.com/image2.jpg" />
<mj-carousel-image src="https://example.com/image3.jpg" />
</mj-carousel>
</mj-column>
</mj-section>
</mj-body>
</mjml>The mjml-carousel package is built around the MJML component system:
Main carousel container that orchestrates image display, navigation controls, and thumbnail generation.
class MjCarousel extends BodyComponent {
static componentName: string; // 'mj-carousel'
static allowedAttributes: object;
static defaultAttributes: object;
/**
* @param initialDatas - Component initialization data including children and attributes
*/
constructor(initialDatas?: object): void;
/**
* Generates CSS styles for carousel functionality including radio button selectors
* @returns CSS string for component head styles
*/
componentHeadStyle(): string;
/**
* Returns style configuration object for different carousel elements
* @returns Object containing CSS styles organized by element type
*/
getStyles(): StyleConfig;
/**
* Calculates thumbnail width based on container width and number of images
* @returns CSS width value as string
*/
thumbnailsWidth(): string;
/**
* Extracts attributes from all child carousel images
* @returns Array of attribute objects from child components
*/
imagesAttributes(): object[];
/**
* Generates HTML for radio button inputs used for carousel navigation
* @returns HTML string containing all radio inputs
*/
generateRadios(): string;
/**
* Generates HTML for thumbnail navigation (if thumbnails are visible)
* @returns HTML string for thumbnail navigation or empty string
*/
generateThumbnails(): string;
/**
* Generates navigation control icons (previous/next arrows)
* @param direction - Either 'previous' or 'next'
* @param icon - URL of the icon image to use
* @returns HTML string for navigation controls
*/
generateControls(direction: string, icon: string): string;
/**
* Generates the main image container with all carousel images
* @returns HTML string containing image container and all images
*/
generateImages(): string;
/**
* Generates the complete carousel table structure
* @returns HTML string for the main carousel table
*/
generateCarousel(): string;
/**
* Generates fallback content for email clients that don't support CSS
* @returns HTML string with MSO conditional tags for fallback
*/
renderFallback(): string;
/**
* Main render method that outputs the complete carousel HTML
* @returns Complete HTML string for the carousel component
*/
render(): string;
}Allowed Attributes:
interface CarouselAttributes {
align?: 'left' | 'center' | 'right'; // Default: 'center'
'border-radius'?: string; // CSS unit(px,%), default: '6px'
'container-background-color'?: string; // CSS color
'icon-width'?: string; // CSS unit(px,%), default: '44px'
'left-icon'?: string; // URL, default: 'https://i.imgur.com/xTh3hln.png'
padding?: string; // CSS unit(px,%), 1-4 values
'padding-top'?: string; // CSS unit(px,%)
'padding-bottom'?: string; // CSS unit(px,%)
'padding-left'?: string; // CSS unit(px,%)
'padding-right'?: string; // CSS unit(px,%)
'right-icon'?: string; // URL, default: 'https://i.imgur.com/os7o9kz.png'
thumbnails?: 'visible' | 'hidden'; // Default: 'visible'
'tb-border'?: string; // CSS border format, default: '2px solid transparent'
'tb-border-radius'?: string; // CSS unit(px,%), default: '6px'
'tb-hover-border-color'?: string; // CSS color, default: '#fead0d'
'tb-selected-border-color'?: string; // CSS color, default: '#ccc'
'tb-width'?: string; // CSS unit(px,%), auto-calculated if not specified
}Usage Examples:
<!-- Basic carousel -->
<mj-carousel>
<mj-carousel-image src="image1.jpg" />
<mj-carousel-image src="image2.jpg" />
</mj-carousel>
<!-- Customized carousel -->
<mj-carousel
align="left"
thumbnails="hidden"
border-radius="10px"
tb-hover-border-color="#ff6600">
<mj-carousel-image src="image1.jpg" alt="Product 1" />
<mj-carousel-image src="image2.jpg" alt="Product 2" />
</mj-carousel>Individual image component within carousel supporting linking, custom thumbnails, and detailed configuration.
class MjCarouselImage extends BodyComponent {
static componentName: string; // 'mj-carousel-image'
static endingTag: boolean; // true - can contain HTML content
static allowedAttributes: object;
static defaultAttributes: object;
/**
* Returns style configuration object for image, thumbnail, and radio elements
* @returns Object containing CSS styles for different image states and elements
*/
getStyles(): ImageStyleConfig;
/**
* Renders the thumbnail version of the image for navigation
* @returns HTML string for thumbnail link with image
*/
renderThumbnail(): string;
/**
* Renders the radio button input for this carousel image
* @returns HTML string for radio input element
*/
renderRadio(): string;
/**
* Main render method that outputs the carousel image HTML
* @returns HTML string for the main carousel image with optional link wrapper
*/
render(): string;
}Allowed Attributes:
interface CarouselImageAttributes {
alt?: string; // Image alt text, default: ''
href?: string; // Link URL when image is clicked
rel?: string; // Link relationship attribute
target?: string; // Link target, default: '_blank'
title?: string; // Image title/tooltip
src?: string; // Main image source URL
'thumbnails-src'?: string; // Separate thumbnail image source
'border-radius'?: string; // CSS unit for image border radius
'tb-border'?: string; // CSS border for thumbnail
'tb-border-radius'?: string; // CSS unit for thumbnail border radius
'css-class'?: string; // Additional CSS class names
}Usage Examples:
<!-- Basic image -->
<mj-carousel-image src="https://example.com/product.jpg" />
<!-- Image with link and custom thumbnail -->
<mj-carousel-image
src="https://example.com/product.jpg"
thumbnails-src="https://example.com/product-thumb.jpg"
href="https://example.com/product-page"
alt="Premium Product"
title="Click to view product details" />
<!-- Image with custom styling -->
<mj-carousel-image
src="https://example.com/image.jpg"
border-radius="15px"
css-class="featured-image" />Custom Navigation Icons:
<mj-carousel
left-icon="https://example.com/custom-left.png"
right-icon="https://example.com/custom-right.png"
icon-width="60px">
<mj-carousel-image src="image1.jpg" />
<mj-carousel-image src="image2.jpg" />
</mj-carousel>Thumbnail Styling:
<mj-carousel
tb-width="80px"
tb-border="3px solid #ddd"
tb-border-radius="8px"
tb-hover-border-color="#007bff"
tb-selected-border-color="#28a745">
<mj-carousel-image src="image1.jpg" />
<mj-carousel-image src="image2.jpg" />
</mj-carousel>// Base component types from mjml-core
interface BodyComponent {
constructor(initialDatas?: object): void;
getAttribute(name: string): string;
htmlAttributes(attributes: object): string;
renderChildren(children: any[], options?: object): string;
context: {
containerWidth: string;
parentWidth: number;
};
props: {
children: any[];
index: number;
};
attributes: object;
}
// CSS Properties type
interface CSSProperties {
[property: string]: string | number;
}
// Style configuration object for MjCarousel
interface StyleConfig {
carousel: {
div: CSSProperties;
table: CSSProperties;
};
images: {
td: CSSProperties;
};
controls: {
div: CSSProperties;
img: CSSProperties;
td: CSSProperties;
};
}
// Style configuration object for MjCarouselImage
interface ImageStyleConfig {
images: {
img: CSSProperties;
firstImageDiv: CSSProperties;
otherImageDiv: CSSProperties;
};
radio: {
input: CSSProperties;
};
thumbnails: {
a: CSSProperties;
img: CSSProperties;
};
}The carousel component includes extensive compatibility features:
Fallback Behavior: