What is Splitting?
Splitting is a JavaScript microlibrary with a collection of small built-in plugins designed to split (section off) an element in a variety of ways, such as words, characters, child nodes, and more!
The Splitting library does not handle any animation, but it gives you the elements and tools needed to create animations & transitions with JavaScript animation libraries or only CSS!. Most plugins utilize a series of <span>
s populated with CSS variables and data attributes that empower you to build all kinds of animations, transitions and interactions.
The general flow is:
Splitting()
is called on atarget
(see: Basic Usage)- Create
<span>
s to inject intotarget
, or query children oftarget
- Index with CSS variables (
<span class="word" style="--word-index: 0">
) - Add the total to the target (
<div data-splitting style="--word-total: 3">
) - Return an array of the splits (see: Returns)
- Animate those elements with CSS or JavaScript!
Get Started
Start playing around with your own Splitting demo on CodePen with this template that includes all of the essentials!
Basic Usage
Splitting can be called without parameters, automatically splitting all elements with data-splitting
attributes by the default of chars
which wraps the element's text in <span>
s with relevant CSS vars.
Initial DOM
<div data-splitting>ABC</div>
<script> Splitting(); </script>
DOM Output
<div data-splitting class="words chars splitting" style="--word-total:1; --char-total:3;"><span class="word" data-word="ABC" style="--word-index:0;"><span class="char" data-char="A" style="--char-index:0;">A</span><span class="char" data-char="B" style="--char-index:1;">B</span><span class="char" data-char="C" style="--char-index:2;">C</span></span></div>
The aftermath may seem verbose, but this won't be visible to the end user. They'll still just see "ABC", but now you can style, animate and transition all of those characters individually!
Splitting will automatically add a splitting
class to the targetted element after it's been run. Each plugin will add their own classes to splits/parent as needed ( char
for chars
, word
for words
, etc. ).
[data-splitting]
Attribute
Fill the data-splitting
attribute with specific plugin names to split with plugin when you call Splitting()
.
<h1 data-splitting>Split by chars (default)</h1>
<p data-splitting="words">Split by words</p>
<ul data-splitting="items">
<li>Split</li>
<li>by</li>
<li>children!</li>
</ul>
<script> Splitting(); </script>
Options
Splitting()
takes a single Object parameter for options. The default options are shown below, and some plugins offer expanded options.
Splitting({
/* target: String selector, Element, Array of Elements, or NodeList */
target: "[data-splitting]",
/* by: String of the plugin name */
by: "chars",
/* key: Optional String to prefix the CSS variables */
key: null
});
Installation
Why bother with build systems or files? Use the CodePen Template to make your own Splitting demo!
Using NPM
Install Splitting from NPM:
npm install splitting --save
Import Splitting from the package and call it. The CSS imports may vary depending on your bundler.
import "splitting/dist/splitting.css";
import "splitting/dist/splitting-cells.css";
import Splitting from "splitting";
Splitting();
Using a CDN
TIP
CDN use is only recommended for demos / experiments on platforms like CodePen. For production use, bundle Splitting using the NPM package with Webpack or your preferred code bundler.
You can get the latest version of Splitting off of the unpkg CDN and include the necessary files as follows.
<link rel="stylesheet" href="https://unpkg.com/splitting/dist/splitting.css" />
<link rel="stylesheet" href="https://unpkg.com/splitting/dist/splitting-cells.css" />
<script src="https://unpkg.com/splitting/dist/splitting.min.js"></script>
Then call Splitting on document load/ready or in a script at the bottom the of the <body>
.
<script> Splitting(); </script>
Recommended Styles
Included in the package are two small stylesheets of recommended CSS that will make text and grid based effects much easier. These styles are non-essential, but provide a lot of value.
splitting.css
includes many extra CSS Variables and psuedo elements that help power advanced animations, especially for text.splitting-cells.css
contain the basic setup styles for cell/grid based effects you'd otherwise need to implement yourself.
Browser Support
Splitting should be thought of as a progressive enhancer. The basic functions work in any halfway decent browser (IE11+). Browsers that support CSS Variables ( ~85% of the current browser market share ) will have the best experience. Browsers without CSS Variable support can still have a nice experience with at least some animation, but features like index-based staggering may not be feasible without JavaScript.
The styles in splitting-cells.css
for the cells
plugin rely on display: grid
, so there may be additional browser limitations. In general, all browsers that support CSS variables also support grid so you should be in the clear.
Plugins
Plugins are the heart of Splitting, each performing a specific split on the targeted element(s). Some plugins have dependencies that will automatically run when called. For example chars
will automatically split by words
to prevent issues with text wrapping.
Each plugin should return a property matching the plugin name containing the split elements. Some plugins have additional options you can pass directly in the main options object for specific uses.
words
The words
plugin splits an element's text into separate words, wrapping each in a <span>
populated with CSS variables and data attributes.
Dependencies | None |
Classes | .word added to each word <span> |
Usage
<div id="target">Splitting Text</div>
<script>
const target = document.querySelector('#target');
const results = Splitting({ target: target, by: 'words' });
// results[0].el = <div id="target" class="splitting words" style="--word-total: 2">...</div>
// results[0].words[0] = <span class="word" data-word="Splitting" style="--word-index: 0">...</span>
// results[0].words[1] = <span class="word" data-word="Text" style="--word-index: 1">...</span>
</script>
chars
Dependency: words
The chars
plugin splits an element's text into separate characters. Before it can run, it splits by words to prevent issues with text wrapping. chars
is the default plugin if no other plugin is specified.
Passing whitespace: true
causes the space between words to be counted toward the character index, though whitespace is collapsed while splitting so that there won't be more than one space character between words.
lines
Dependency: words
The lines
plugin splits an element into separate words and then groups them by the line. It automatically runs the words
plugin.
Usage
<div id="target">Splitting<br /> Text</div>
<script>
const target = document.querySelector('#target');
const results = Splitting({ target: target, by: 'lines' });
results[0].el // <div id="target" class="splitting lines" style="--line-total: 1; --word-total: 2">...</div>
results[0].words[0] // <span class="word" data-word="Splitting" style="--word-index: 0">...</span>
results[0].words[1] // <span class="word" data-word="Text" style="--word-index: 1">...</span>
results[0].lines[0][0] // <span class="word" data-word="Splitting" style="--word-index: 0">...</span>
</script>
items
The items
plugin indexes existing elements. It applies an --item-index
to each matching element and --item-total
to the target. If matching
is not specified, the direct element children will be selected.
Usage
<div class="container">
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
</div>
<script>
const results = Splitting({
target: '.container',
by: 'items',
matching: 'li'
});
results[0].items[0] // <li style="--item-index: 0">One</li>
results[0].items[1] // <li style="--item-index: 1">Two</li>
results[0].items[2] // <li style="--item-index: 2">Three</li>
</script>
grid
Dependency: cols
, rows
The grid
plugin detects the cols and rows of a layout by comparing the distance from the edges of the container. Plainly speaking, it assigns each selected element a row and column index. It automatically runs the rows
and cols
plugins.
Usage
<div class="container">
<div>
<div class="col" id="1"></div>
<div class="col"></div>
<div class="col"></div>
</div>
<div>
<div class="col" id="2"></div>
<div class="col"></div>
<div class="col"></div>
</div>
</div>
<script>
const results = Splitting({
target: '.container',
by: 'grid',
matching: '.col'
});
results[0].rows[0][0] // <div id="1" style="--row-index: 0; --col-index: 0">...</div>
results[0].rows[0][1] // <div style="--row-index: 0; --col-index: 1">...</div>
results[0].rows[0][2] // <div style="--row-index: 0; --col-index: 2">...</div>
results[0].rows[1][1] // <div id="2" style="--row-index: 1; --col-index: 0">...</div>
results[0].rows[1][2] // <div style="--row-index: 1; --col-index: 1">...</div>
results[0].rows[1][3] // <div style="--row-index: 1; --col-index: 2">...</div>
results[0].cols[0][0] // <div id="1" style="--row-index: 0; --col-index: 0">...</div>
results[0].cols[1][0] // <div style="--row-index: 0; --col-index: 1">...</div>
results[0].cols[2][0] // <div style="--row-index: 0; --col-index: 2">...</div>
results[0].cols[0][1] // <div id="2" style="--row-index: 1; --col-index: 0">...</div>
results[0].cols[1][1] // <div style="--row-index: 1; --col-index: 1">...</div>
results[0].cols[2][1] // <div style="--row-index: 1; --col-index: 2">...</div>
</script>
cols
The cols
plugin detects the cols of a layout by comparing the distance from the left of the container.
Usage
<div class="container">
<div>
<div class="col" id="1"></div>
<div class="col"></div>
</div>
<div>
<div class="col" id="2"></div>
<div class="col"></div>
</div>
</div>
<script>
const results = Splitting({
target: '.container',
by: 'cols',
matching: '.col'
});
results[0].cols[0][0] // <div id="1" style="--col-index: 0">...</div>
results[0].cols[1][0] // <div style="--col-index: 1">...</div>
results[0].cols[0][1] // <div id="2" style="--col-index: 0">...</div>
results[0].cols[1][1] // <div style=" --col-index: 1">...</div>
</script>
rows
The rows
plugin detects the rows of a layout by comparing the distance from the top of the container.
Usage
<div class="container">
<div>
<div class="col" id="1"></div>
<div class="col"></div>
</div>
<div>
<div class="col" id="2"></div>
<div class="col"></div>
</div>
</div>
<script>
const results = Splitting({
target: '.container',
by: 'rows',
matching: '.col'
});
results[0].rows[0][0] // <div id="1" style="--row-index: 0; --col-index: 0">...</div>
results[0].rows[0][1] // <div style="--row-index: 0;">...</div>
results[0].rows[1][1] // <div id="2" style="--row-index: 1; --col-index: 0">...</div>
results[0].rows[1][2] // <div style="--row-index: 1;">...</div>
</script>
cells
Cells requires an additional .css file to properly split images. Please include /dist/splitting-cells.css in your page to use this feature.
The cells
plugin generates <span>
s based on the number of rows and columns provided. This plugin is perfect for splitting an picture with the image
option, which applies an image as a background-image
to the target
. Set a specific image with image: 'http://url-to-image'
or use image: true
detect the first <img />
in the container for use.
Usage
<div class="image">
<img src="http://unsplash.it/200/200?random" />
</div>
<script>
const results = Splitting({
target: '.image',
by: 'cells',
image: true,
cols: 2,
rows: 2
});
results[0].el // <div class="image splitting cells" style="background-image: url(http://unsplash.it/200/200?random); --cell-total: 4; --row-total: 2; --col-total: 2;">...</div>
results[0].cells[0] // <span class="cell" style="--cell-index: 0; --row-index: 0; --col-index: 0"></span>
results[0].cells[1] // <span class="cell" style="--cell-index: 1; --row-index: 0; --col-index: 1"></span>
results[0].cells[3] // <span class="cell" style="--cell-index: 2; --row-index: 1; --col-index: 0"></span>
results[0].cells[4] // <span class="cell" style="--cell-index: 3; --row-index: 1; --col-index: 1"></span>
</script>
Make Your Own!
Splitting is easily expandable to create your own splits. See the API for Splitting.add()
for more details. Be sure to share your plugins and demos with #splittingjs!
API
Splitting()
Options
Options | Description |
---|---|
target | An optional list of elements or a css selector. By default, this is [data-splitting] |
by | The splitting plugin to use. See the plugin page for a full list. If not specified, the value of the data-splitting attribute will be use. If that is not present, the chars plugin will be used. |
key | An optional key used as a prefix on on CSS Variables. For instance when a key of hero is used with the chars plugin, it will changethe CSS variable --char-index to --hero-char-index . This should be used if multiple splits have been performed on the same element, or to resolve conflicts with other libraries. |
Plugin-specific Options
Options | Description |
---|---|
matching | Used by the following plugins to select children to index: items , grid , cols , rows , cellRows , cellCols , and cells . If not specified, the immediate child elements will be selected. |
cols | The number of columns to create or detect. This is used by the following plugins: cols , cellCols , grid , and cells |
rows | The number of rows to create or detect. This is used by the following plugins: rows , cellRows , grid , and cells |
whitespace | If true, the chars plugin will count whitespace while indexing characters. |
Returns
The Splitting
fucntion always returns an array of objects with the following properties based on plugin name, giving you access to each element's splits to use with JavaScript animation libraries or for additional processing.
<div data-splitting>Splitting Text</div>
<script>
const results = Splitting();
results[0].el // <div data-splitting class="splitting chars words" style="--word-total: 2; --char-total: 13">...</div>
results[0].words[0] // <span class="word" data-word="Splitting" style="--word-index: 0">...</span>
results[0].words[1] // <span class="word" data-word="Text" style="--word-index: 1">...</span>
results[0].chars[0] // <span class="char" data-char="S" style="--char-index: 0">S</span>
results[0].chars[1] // <span class="char" data-char="p" style="--char-index: 1">p</span>
</script>
Property | Type | Description |
---|---|---|
chars | HTMLElement[] | An array of all characters created by the chars plugin |
words | HTMLElement[] | An array of all words created by the words and lines plugin |
lines | HTMLElement[][] | An array of element arrays by the line, returned by the lines plugin |
items | HTMLElement[] | An array of elements returned by the items plugin. |
rows | HTMLElement[][] | An array of element arrays by row, returned by the rows and grid plugin |
cols | HTMLElement[][] | An array of element arrays by column, returned by the cols and grid plugin |
cells | HTMLElement[] | An array of cells created by cells , cellRows , or cellCols plugin |
cellRows | HTMLElement[][] | An array of element arrays by the row, returned by the cellRows and cells plugin |
cellCols | HTMLElement[][] | An array of element arrays by the column, returned by the cellCols and cells plugin |
Splitting.html()
The Splitting.html()
function takes the same options as Spitting()
but has a required property of content
. The content
property should be an html string to be used as the splitting target. The Splitting.html()
function returns a string of the rendered HTML instead of returning a result object. This function is intended to be used inside of JS Framework DSL's such as the Vue templating language:
<div v-html="Splitting.html({ content: myContentString, by: 'chars' })"></div>
Splitting.add()
Options | Description |
---|---|
by | The name of the plugin. It must be unique. |
key | The prefix to set when adding index/total css custom properties to the elements. |
split | The function to call when this plugin is used. The return value is set in the result of Splitting() as the same name as the by in the plugin. |
depends | The plugins that must run prior to this plugin. |