Carousels, slideshows, sliders, whatever you call them, are controversial and complex pieces of our web interactions. More often than not, they’re a means to shove a bunch of ideas into a single part of the user interface. Usually, clients follow the herd mentality and request they have one, or it becomes a means for multiple stakeholders to compromise on what takes precedence in information architecture.
We all know they could be better for overall site performance and offer many user experience obstacles. So, why would you want to build one? 🙃
I’m making some compelling counter-arguments, but there is still a time and place when you will need one, and we’ll cover all the steps to create your own.
Table of Content
As of writing this, no slider block is currently available in WordPress core’s library. There are several existing slider block plugins, but we want to have control over and learn the intricacies of our own. This way, we can focus on keeping our code lean and agile and extend it to our needs.
I’m not going to lie, there are a lot of steps to get things like this working, but you’ll learn a lot along the way, like:
- Working with and extending the
@wordpress/scripts
package. - Pulling in 3rd-party dependencies and integrating them to behave smoothly within the WordPress editor.
- Use
@wordpress/components
to allow your clients to modify the properties of the slider. - And much more.
Here is a demonstration of what we’ll be creating.
Prerequisites
Beyond some working knowledge of HTML, CSS, PHP, and JavaScript. You’ll also need familiarity with the following:
- Node and npm: You should have Node.js and npm installed on your machine. I recommend using nvm (node version manager), which allows you to install and manage different versions of Node easily.
- Block development: Preferably, you’ve at least built your first block and are familiar with the key concepts and files that make up block registration and rendering (editor and front end).
- Build tools: Preferably, you’re already familiar with
@wordpress/create-block
and@wordpress/scripts
, and you’re comfortable running commands from a Command Line Interface (CLI).
Why SwiperJS?
There are many slider libraries out there that are drop-in solutions. We want one with a history of stability, extendability, and modularity. This way, we can pull in bits and pieces of things we need and leave out what we do not want. SwiperJS has been around for a while and is very modular.
Check out the SwiperJS Demos page to see all possible variations you can create.
Setting Up
First, we need to create a block and a WordPress plugin to organize our custom functionality and the @wordpress/create-block
tool is super handy for this.
Generate Our Plugin and Block Files
Create our WordPress plugin and first block with @wordpress/create-block
npx @wordpress/create-block@latest slider --namespace wpe --variant dynamic && cd slider
Code language: Bash (bash)
Let’s break down what happened for those new to the @wordpress/create-block
package. Behind the scenes, @wordpress/create-block
does a lot of things for us, including establishing our NPM developer dependencies, which include the helpful @wordpress/scripts
package, and creating a Slider block plugin with the following organization:
slider.php
– The main plugin file, which registers a slider block.src/
– This is where the@wordpress/create-block
package places our block’s files.build/
– This is where the@wordpress/scripts
package will compile and create our block build for us. We should not have to modify anything in the directory, as it is overwritten each time with compiled assets.
The valuable @wordpress/scripts
package is worth exploring if you’re new to its capabilities. For now, know that it is a series of reusable webpack-driven scripts that can watch and compile our final block assets for us.
Final directory structure after running @wordpress/create-block
.
├── build
│ ├── block.json
│ ├── index.asset.php
│ ├── index.css
│ ├── index.js
│ ├── render.php
│ ├── style-index.css
│ ├── view.asset.php
│ └── view.js
├── package.json
├── readme.txt
├── slider.php
└── src
├── block.json
├── edit.js
├── editor.scss
├── index.js
├── render.php
├── style.scss
└── view.js
Code language: CSS (css)
The #1 local WordPress
development tool
Activate Plugin and Test Our Initial Progress
We’ve finished our first round of setting up and scaffolding our plugin. Let’s activate the Slider plugin in a WordPress development environment to ensure we can insert the Slider block in the editor.
It is always good to check your progress! Of course, there is not much to see, and we have a simple block with a blue background right now. This is what @wordpress/create-block
typically gives us to start.
Install Our Dependencies
We want to install our project dependencies, including swiper
(for SwiperJS, of course), postcss-import
, and postcss-preset-env
, which allows us to import SwiperJS’s CSS when it is time.
Our one-liner for installing our dependencies and developer dependencies.
npm install --save swiper && npm install --save-dev postcss-import postcss-preset-env
Code language: Bash (bash)
Configure PostCSS
By default, when we created our WordPress plugin and the initial block with the @wordpress/create-block
package it installed @wordpress/scripts
as a devDependency
. The @wordpress/scripts
package comes with a pre-configured webpack setup, which includes PostCSS. We need to extend the existing PostCSS configuration to recognize and handle the CSS @import
statements that we’ll use to roll up all of SwiperJS’s CSS with any of our own.
Be sure to create a new postcss.config.js
file in the root of your plugin and place the following code within.
Our postcss.config.js
file configures PostCSS to allow importing of Swiper’s CSS modules.
module.exports = () => {
const config = {
plugins: {
'postcss-import': {},
'postcss-preset-env': {},
},
};
return config;
};
Code language: JavaScript (javascript)
This will come in handy later when we update the src/styles.scss
.
Verifying Our Initial Plugin Setup
We should now have our WordPress plugin, a Slider block, and our dependencies installed. Great!
We’ll focus on extending our Slider block for the remainder of this tutorial. Be sure to start watching your block for changes and compiling them automatically in the background. You can do this by running npm start
, which tells @wordpress/scripts
to watch our block for changes and compile them if anything is changed (to the build/
directory).
Check out the final codebase Slider Block GitHub repo. Feel free to download the final plugin or fork the repo and make it all your own.
Planning Our Block Customizations
When you’re getting ready to create a custom block, planning what you’ll need and what already exists that you can leverage is ideal.
We want to allow users to add a Slider block to the editor and automatically have it populated with example slides. We will utilize WordPress’s existing Cover block to represent our slides. This gives us existing affordances like image attachment, overlay colors, and nesting of additional blocks (Columns, Buttons, Headings, and many more).
With this in mind, we’ll update our slider block’s block.json
.
Extending the Slider Block
We’ll open the Slider block’s block.json
file and update the overall block’s definitions.
The Slider block’ssrc/block.json
file is where we extend definitions for the overall block.
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "wpe/slider",
"title": "Slider",
"category": "widgets",
"description": "Display your images in a horizontal carousel.",
"icon": "slides",
"keywords": ["carousel", "slideshow"],
"attributes": {
"autoplay": {
"type": "boolean",
"default": true
},
"navigation": {
"type": "boolean",
"default": true
},
"pagination": {
"type": "boolean",
"default": true
}
},
"example": {},
"supports": {
"html": false,
"align": ["wide", "full"],
"className": true,
"color": {
"background": true,
"gradients": true,
"link": true,
"text": true
},
"spacing": {
"padding": true,
"margin": ["top", "bottom"]
}
},
"textdomain": "wpe",
"version": "0.1.0",
"editorScript": "file:./index.js",
"editorStyle": "file:./index.css",
"render": "file:./render.php",
"style": "file:./style-index.css",
"viewScript": "file:./view.js"
}
Code language: JSON / JSON with Comments (json)
We’re defining some new attributes
for the Slider block, which we’ll use to allow users to choose whether they want certain features assigned to each Slider block. In our case, we’ll let them toggle whether the slider should autoplay and have navigation or pagination. Check out this Block API Reference if you want to dig deeper into how attributes work.
We also want our Slider block to opt into certain features that WordPress offers blocks, like alignment, colors, and spacing. This is why we’re defining supports
in our block.json
. Be sure to check out the complete list of Block Supports and consider extending what is here to offer additional features.
Import SwiperJS and Create a Default Object
We’re going to try to keep things organized (why not). Let’s import all of our SwiperJS dependencies and create a simple default SwiperJS object that we can utilize in both our editor (back-end) and front-end views.
Create a new src/swiper-init.js
file.
We’re importing all of our Swiper JavaScript core and module dependencies and setting up a default object, which we can later use in multiple contexts.
/**
* Swiper dependencies
*
* @see https://swiperjs.com/get-started
*/
import { Swiper } from 'swiper';
import { Autoplay, Keyboard, Navigation, Pagination } from 'swiper/modules';
/**
* Initialize the slider.
*
* @param {Element} container HTMLElement.
* @param {Object} options Slider parameters.
*
* @return {Object} Returns initialized slider instance.
*
* @see https://swiperjs.com/swiper-api#parameters
*/
export function SwiperInit( container, options = {} ) {
const parameters = {
autoplay: options?.autoplay ?? true,
centeredSlides: options?.centerSlides ?? false,
createElements: true,
grabCursor: options?.grabCursor ?? true,
initialSlide: 0,
keyboard: true,
modules: [ Autoplay, Keyboard, Navigation, Pagination ],
navigation: options?.navigation ?? false,
pagination: options?.pagination ?? false,
simulateTouch: options?.simulateTouch ?? true,
};
return new Swiper( container, parameters );
}
Code language: JavaScript (javascript)
We’re importing Swiper and some key Swiper modules at the top of the swiper-init.js
file, and then we’re exporting our SwiperInit()
function, which contains some defaults for us to return a new Swiper()
instance.
Import SwiperJS CSS Styling
We’ll want to pull in SwiperJS’s CSS as well, which is critical to allowing the slider to slide.
Open up the existing src/style.scss
and replace it with the following.
We’re importing our Swiper CSS dependencies and applying some of our own styles in src/style.scss
@import "swiper/css";
@import "swiper/css/a11y";
@import "swiper/css/autoplay";
@import "swiper/css/navigation";
@import "swiper/css/pagination";
.wp-block-wpe-slider {
--swiper-theme-color: var(--wp--preset--color--accent, var(--wp--preset--color--primary));
--swiper-navigation-size: 48px;
--swiper-navigation-color: var(--swiper-theme-color);
--swiper-pagination-bullet-horizontal-gap: 0.25rem;
--swiper-pagination-bullet-vertical-gap: 0.25rem;
--swiper-pagination-bullet-size: 0.75rem;
--swiper-pagination-bullet-opacity: 1;
--swiper-pagination-bullet-inactive-color: black;
--swiper-pagination-bullet-inactive-opacity: .2;
}
Code language: CSS (css)
Remember, we set up a custom postcss.config.js
file earlier? This was critical to allow the @wordpress/scripts
dependency, which we’re using to watch and build our final blocks, to be able to recognize and inspect dependencies from our install node_modules
directory. This allows us to pull our CSS dependencies from our install swiper
dependency.
Of course, this file is watched and pulled in as a dependency through the src/index.js
file. Open it up, and you’ll see the existing import './style.scss';
near the top. Ultimately, this file is compiled and written to the final build/style-index.css
and defined as a dependency in the Slider’s block.json
file (via the "style"
). This tells WordPress to load the CSS in both the editor and the front end.
Create a New constants.js
File
I prefer to keep some key variables in a separate constants.js
file. This allows fellow developers to quickly open it up and change key parameters for our final slider (if they choose to 😉).
Let’s create a new constants.js
file and place the following code.
We’re defining key variables in a new src/constants.js
file. We’ll reference these later in the src/slider.js
file.
/**
* These are the block we'll allow to be inserted
* as a slide.
*/
export const ALLOWED_BLOCKS = [ 'core/cover' ];
/**
* This is the default block we'll use for our slide.
*/
export const DEFAULT_BLOCK = 'core/cover';
/**
* These are the attributes we assign for our DEFAULT_BLOCK.
*/
export const DEFAULT_BLOCK_ATTRIBUTES = {
align: 'center',
className: 'swiper-slide',
contentPosition: 'bottom left',
customOverlayColor: '#000000',
dimRatio: 20,
layout: {
type: 'constrained',
},
style: {
color: {
text: '#ffffff',
},
elements: {
heading: {
color: {
text: '#ffffff',
},
},
link: {
color: {
text: '#ffffff',
},
},
},
spacing: {
padding: {
top: 'var:preset|spacing|large',
bottom: 'var:preset|spacing|large',
left: 'var:preset|spacing|large',
right: 'var:preset|spacing|large',
},
},
},
};
/**
* These are the default inner blocks we'll use
* when our DEFAULT_BLOCK is inserted.
*/
export const DEFAULT_INNERBLOCK = 'core/paragraph';
/**
* These are the attributes we assign for our default
* inner blocks.
*/
export const DEFAULT_INNERBLOCK_ATTRIBUTES = {
fontSize: 'large',
style: {
color: {
text: '#ffffff',
},
},
};
/**
* Some default Unsplash images...
* (feel free to replace)
*/
export const PLACEHOLDER_IMG_1 = 'https://source.unsplash.com/kdl8xDDD6iA';
export const PLACEHOLDER_IMG_2 = 'https://source.unsplash.com/cRUZICCU_Xg';
export const PLACEHOLDER_IMG_3 = 'https://source.unsplash.com/lUF3cqG6n7s';
Code language: JavaScript (javascript)
We’ll reference these in our Slider
function-based component.
Are you new to WordPress block development? Perhaps, you’re a seasoned developer and need to brush up on key concepts. Check out Anatomy of a Block.
Define the Slider Edit
Function
The edit.js
file is where we establish all the state and logic for everything the user will see and interact with in the editor.
Add Imports
First, let’s start by adding all of our @import
statements at the top. These include all of our WordPress dependencies, followed by our Slider
component (we’ll create this next) and our editor.scss
.
At the beginning of our src/edit.js
file where we start importing all of our dependencies.
/**
* WordPress dependencies
*/
import {
useBlockProps,
useBlockEditContext,
InspectorControls,
} from '@wordpress/block-editor';
import { PanelBody, PanelRow, ToggleControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
/**
* Internal Dependencies
*/
import { Slider } from './slider';
// Editor styling.
import './editor.scss';
Code language: JavaScript (javascript)
Define the Main Edit
Function
We’re going to define our primary Edit
function next, which you can place right after all your imports in the edit.js
file.
We’re defining our main Edit
function, which references some components we still need to create but will soon.
/**
* The edit function describes the structure of your block in the context of the
* editor. This represents what the editor will render when the block is used.
*
* @see https://developer.wordpress.org/block-editor/developers/block-api/block-edit-save/#edit
*
* @param {Object} props Properties passed to the function.
* @param {Object} props.attributes Available block attributes.
* @param {Function} props.setAttributes Function that updates individual attributes.
*
* @return {Element} Element to render.
*/
export default function Edit( { attributes, setAttributes } ) {
const { autoplay, navigation, pagination } = attributes;
const { clientId } = useBlockEditContext();
const blockProps = useBlockProps();
return (
<>
<div { ...blockProps }>
<Slider attributes={ attributes } clientId={ clientId } />
</div>
<InspectorControls>
<PanelBody title={ __( 'Settings', 'wpe' ) }>
<PanelRow>
<ToggleControl
label={ __( 'Autoplay', 'wpe' ) }
checked={ autoplay }
onChange={ ( value ) =>
setAttributes( { autoplay: value } )
}
help={ __(
'“Autoplay” will automatically advance the slides. Note: this is intentionally disabled in the editor, but will affect the front end.'
) }
/>
</PanelRow>
<PanelRow>
<ToggleControl
label={ __( 'Navigation', 'wpe' ) }
checked={ navigation }
onChange={ ( value ) =>
setAttributes( { navigation: value } )
}
help={ __(
'“Navigation” will display arrows so user can navigate forward/backward.'
) }
/>
</PanelRow>
<PanelRow>
<ToggleControl
label={ __( 'Pagination', 'wpe' ) }
checked={ pagination }
onChange={ ( value ) =>
setAttributes( { pagination: value } )
}
help={ __(
'“Pagination” will display dots along the bottom for user to click through slides.'
) }
/>
</PanelRow>
</PanelBody>
</InspectorControls>
</>
);
}
Code language: JavaScript (javascript)
A lot is happening here; we’ll step through it piece by piece.
In our Edit
function, we’re passing down our block’s attributes for navigation, pagination, and autoplay (line 14). The Edit
function has a built-in function setAttributes
, which allows us to update attribute values conveniently.
We’re using WordPress’s handy PanelBody
, PanelRow
, and ToggleControl
components (near the bottom) to allow users to toggle these features on and off in the editor. Again, we imported these in the previous code snippet placed at the top of the file.
The Slider
component will represent the actual markup for our SwiperJS-driven slider. Let’s get that set up next.
Custom Slider Component with useRefEffect
We’re calling the Slider
component within our Edit
function, which we still need to create. Create a new file called slider.js
and place the following code.
Our Slider
component uses memoization to cache our sliderRef
, which we use to instantiate Swiper.
/**
* WordPress dependencies
*/
import {
store as blockEditorStore,
ButtonBlockAppender,
useInnerBlocksProps,
} from '@wordpress/block-editor';
import { useRefEffect } from '@wordpress/compose';
import { select, subscribe } from '@wordpress/data';
import { memo } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
/**
* Internal Dependencies
*/
import { SwiperInit } from './swiper-init';
import {
ALLOWED_BLOCKS,
DEFAULT_BLOCK,
DEFAULT_BLOCK_ATTRIBUTES,
DEFAULT_INNERBLOCK,
DEFAULT_INNERBLOCK_ATTRIBUTES,
PLACEHOLDER_IMG_1,
PLACEHOLDER_IMG_2,
PLACEHOLDER_IMG_3,
} from './constants';
/**
* Slider component.
*/
export const Slider = memo( ( { clientId, attributes } ) => {
const sliderRef = useRefEffect( ( element ) => {
const options = {
...attributes,
...{
autoplay: false,
grabCursor: false,
simulateTouch: false,
},
};
// Initialize slider.
let slider = SwiperInit( element, options );
// Store the current slide order to detect changes, such as adding, removing, or reordering slides.
let slideOrder = select( blockEditorStore ).getBlockOrder( clientId );
// Subscribe slider update events like adding, removing, or reordering slides.
const unsubscribeSliderUpdateListener = subscribe( () => {
const currentSlidesOrder =
select( blockEditorStore ).getBlockOrder( clientId );
// Check if the slider has been changed.
if ( currentSlidesOrder.toString() !== slideOrder.toString() ) {
const selectedBlock =
select( blockEditorStore ).getSelectedBlock();
const slideAdded =
currentSlidesOrder.length > slideOrder.length;
const slideRemoved =
currentSlidesOrder.length < slideOrder.length;
const slideMoved =
currentSlidesOrder.length === slideOrder.length;
const activeIndex = slider.activeIndex;
// Store the current slide order before destroying the slider instance.
slideOrder = currentSlidesOrder;
slider.destroy();
window.requestAnimationFrame( () => {
// Initialize slider.
slider = SwiperInit( element, options );
// Determine where the slider should go.
let slideToIndex = activeIndex;
if ( slideAdded ) {
slideToIndex = slideOrder.length;
} else if ( slideRemoved ) {
slideToIndex = activeIndex - 1;
} else if ( slideMoved ) {
slideToIndex = slideOrder.findIndex(
( clientId ) => clientId === selectedBlock.clientId // eslint-disable-line no-shadow
);
}
if ( slideToIndex < 0 ) {
slideToIndex = 0;
}
slider.slideTo( slideToIndex, 0 );
} );
}
} );
return () => {
unsubscribeSliderUpdateListener();
slider.destroy();
};
} );
// Our nested innerblocks that will be inserted by default.
const innerBlocksProps = useInnerBlocksProps(
{ className: 'swiper-wrapper' },
{
allowedBlocks: ALLOWED_BLOCKS,
defaultBlock: {
name: DEFAULT_BLOCK,
attributes: {
url: `${ PLACEHOLDER_IMG_3 }`,
...DEFAULT_BLOCK_ATTRIBUTES,
},
},
directInsert: true,
orientation: 'horizontal',
template: [
[
DEFAULT_BLOCK,
{
url: `${ PLACEHOLDER_IMG_1 }`,
...DEFAULT_BLOCK_ATTRIBUTES,
},
[
[
DEFAULT_INNERBLOCK,
{
placeholder: __( 'Slide title…', 'wpe' ),
...DEFAULT_INNERBLOCK_ATTRIBUTES,
},
],
],
],
[
DEFAULT_BLOCK,
{
url: `${ PLACEHOLDER_IMG_2 }`,
...DEFAULT_BLOCK_ATTRIBUTES,
},
[
[
DEFAULT_INNERBLOCK,
{
placeholder: __( 'Slide title…', 'wpe' ),
...DEFAULT_INNERBLOCK_ATTRIBUTES,
},
],
],
],
],
renderAppender: false,
templateInsertUpdatesSelection: true,
}
);
return (
<>
<div className="swiper" ref={ sliderRef }>
<div { ...innerBlocksProps } />
</div>
<ButtonBlockAppender
className="slider-appender has-icon"
rootClientId={ clientId }
/>
</>
);
} );
Code language: JavaScript (javascript)
This is a rather large and complex component that encompasses a lot of functionality. So, let’s break it down.
- Line 5 – We’re utilizing the
useRefEffect
dependency from the@wordpress/compose
package. This is similar to React’suseEffect
, but it allows for a callback when a dependency changes. - Line 44 – We grab our SwiperJS default object and initialize our slider.
- Line 21-66 – We’re utilizing
@wordpress/data
package’ssubscribe()
listener function to watch for state changes and merge the state with our newly instantiated SwiperJS element. This allows us to tell SwiperJS when new slides are shifted around. - Line 95-98 – We’re performing some cleanup for our SwiperJS instance.
- Line 102-152 – This is where we pass in all of our inner block definitions, which will automatically populate the slider when it is inserted with some core blocks.
- Finally, we return our components. We have two main components we’re adding here:
- Our Swiper element, which we assign our
ref
to and pass down theinnerBlockProps
with our blocktemplate
. ButtonBlockAppender
– This is another useful component of the@wordpress/block-editor
package, which allows us to append a button for users to click and add a slide along the bottom of the Slider.
- Our Swiper element, which we assign our
Creating block template
arrays can be tricky. It is usually best to block it all out in the editor, switch to code view, copy and paste the necessary code markup, and utilize the handy WPHTML Converter to convert your markup into JavaScript or PHP.
Define the Slider save
Function
We need to establish our saving logic for our overall slider block. Remember, we have set the Edit
logic, but we still need to ensure our block’s final markup and properties are saved in the post_content
for retrieval and further editing.
We can accomplish this by adding save.js
to our slider block and adding the following code.
We need to add our save
function to save our final slider block markup to post_content
. Create a new file: src/save.js
/**
* WordPress dependencies
*/
import { InnerBlocks } from '@wordpress/block-editor';
/**
* The save function defines the way in which the different attributes should
* be combined into the final markup, which is then serialized by the block
* editor into `post_content`.
*
* @see https://developer.wordpress.org/block-editor/developers/block-api/block-edit-save/#save
*
* @return {Element} Element to render.
*/
export default function Save() {
return <InnerBlocks.Content />;
}
Code language: JavaScript (javascript)
We’re leveraging WordPress’s InnerBlocks
component to return our saved slider content. Then we have to make sure we import our saving file within our block’s entry point: src/index.js
Modify the existing src/index.js
to import
our save
function and return it within the registerBlockType()
handler.
/**
* Registers a new block provided a unique name and an object defining its behavior.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
*/
import { registerBlockType } from '@wordpress/blocks';
/**
* Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
* All files containing `style` keyword are bundled together. The code used
* gets applied both to the front of your site and to the editor.
*
* @see https://www.npmjs.com/package/@wordpress/scripts#using-css
*/
import './style.scss';
/**
* Internal dependencies
*/
import Edit from './edit';
import save from './save';
import metadata from './block.json';
/**
* Every block starts by registering a new block type definition.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
*/
registerBlockType( metadata.name, {
/**
* @see ./edit.js
*/
edit: Edit,
/**
* @see ./save.js
*/
save,
} );
Code language: JavaScript (javascript)
Define the render.php
Display Logic
We must establish our final display logic for the block, which visitors will see for the end product. This is all handled within the block’s render.php
.
The src/render.php
file is where we handle our final display logic.
<?php
/**
* Slider block
*
* @var array $attributes Block attributes.
* @var string $content Block default content.
* @var \WP_Block $block Block instance.
*/
$autoplay = empty( $attributes['autoplay'] ) ? false : $attributes['autoplay'];
$navigation = empty( $attributes['navigation'] ) ? false : $attributes['navigation'];
$pagination = empty( $attributes['pagination'] ) ? false : $attributes['pagination'];
$swiper_attr = array(
'autoplay' => $autoplay,
'navigation' => $navigation,
'pagination' => $pagination,
);
$swiper_attr = htmlspecialchars( wp_json_encode( $swiper_attr ) );
$wrapper_attributes = get_block_wrapper_attributes(
array(
'class' => 'swiper',
)
);
?>
<div <?php echo wp_kses_data( $wrapper_attributes ) . 'data-swiper="' . esc_attr( $swiper_attr ) . '"'; ?>>
<div class="swiper-wrapper">
<?php echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
</div><!-- .swiper -->
Code language: PHP (php)
In the code above, we’re checking for our $autoplay
, $navigation
, $pagination
settings and assigning them as data attributes to our final <div>
. It is crucial to merge these properties with get_block_wrapper_attributes()
, which allows us to pass through the items we added to our slider block.json
"supports"
definition. If a user wants to alter the alignment or colors of the block, then this is how WordPress will be aware of these final attributes.
Update view.js
Front End JavaScript
We will import our handy ./swiper-init
again and reuse this within our front-end instantiation code. Open up the src/view.js
file and replace it with the following code.
Within the src/view.js
is where the front-end JavaScript for our block is established and enqueued within WordPress’s dependency queue.
/**
* Shared Swiper config.
*/
import { SwiperInit } from './swiper-init';
document.addEventListener( 'DOMContentLoaded', () => {
const containers = document.querySelectorAll( '.swiper' );
// Return early, and often.
if ( ! containers.length ) {
return;
}
// Loop through all sliders and assign Swiper object.
containers.forEach( ( element ) => {
// We could pass in some unique options here.
let options = {};
try {
options = JSON.parse( element.dataset.swiper );
} catch ( e ) {
// eslint-disable-next-line no-console
console.error( e );
return;
}
// Slider 🚀
SwiperInit( element, options );
} );
} );
Code language: JavaScript (javascript)
Final Build & Next Steps
If you had npm start
running in the background the whole time then you should be in an excellent place to test things out. Otherwise, feel free to run npm run build
to create a final build of your blocks, open up a new post, add a slider block, and test everything out.
Remember that SwiperJS has a lot of bells and whistles, and we’ve created an opinionated version of a slider. You could keep going further and consider extending things, like:
- Pull in some more SwiperJS modules, like doing a Grid slider, or a Vertical slider.
- Consider pulling in the Accessibility (a11y) module and be sure to announce slide progression to screen readers.
- Consider utilizing Block Variations or Block Styles to offer users different variations of your slider block.
Check out the final codebase Slider Block GitHub repo. Feel free to download the final plugin or fork the repo and make it all your own.
Conclusion
I hope you found this tutorial helpful and easy to follow. It was quite the journey, and we covered a lot of ground. Please let me know if you hit any hurdles along the way or if you went even further with your Slider block.
Don’t be shy; reach out on Twitter if you want to share or have any questions.