MJML component for creating interactive image carousels in email templates with thumbnail navigation and cross-client compatibility
npx @tessl/cli install tessl/npm-mjml-carousel@4.15.0MJML 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: