jQueryかJSでテキストを1文字ずつspanで囲う方法(空白・改行削除対応)

Java Script

見出しなどにJSでデザインを加えるときに、1文字ずつアニメーションを加えたいことがありますよね。HTMLで1文字ずつにspanを書き足すのは非現実的なので、jQueryで対象のテキストに一括でspanを追加してしまいましょう。

やりたいこと

<!-- 元のHTML -->
<h1 id="js-page-title">
    About us
</h1>

<!-- 1文字ずつspanを加えたHTMLにしたい -->
<h1 id="js-page-title">
    <span>A</span><span>b</span><span>o</span><span>u</span><span>t</span> <span>u</span><span>s</span>
</h1>

<!--
わかりやすいように改行すると以下のようなイメージです。
実際には半角スペースが含まれてしまうため改行しない。
-->
<h1 id="js-page-title">
    <span>A</span>
    <span>b</span>
    <span>o</span>
    <span>u</span>
    <span>t</span>

    <span>u</span>
    <span>s</span>
</h1>

結論

/**
 * jQuery版
**/

// コンテナを指定する
var container = $("#js-page-title");

// コンテナのコンテンツを取得
var content = $(container).html();

// コンテンツから空白や改行を削除
var text = $.trim(content);

// 新しく挿入するHTMLの変数を定義
var newHtml = "";

// text を1文字ずつ分割して span を追加する
text.split("").forEach(function(v) {
    newHtml += "<span>" + v + "</span>";
});

// コンテナに作ったHTMLを挿入しする
$(container).html(html);


/**
 * JS版
**/

// コンテナを指定する
var container = document.querySelector('#js-page-title'); // JS版

// コンテナのコンテンツを取得
var content = container.textContent;

// コンテンツから空白や改行を削除
var text = content.trim(); // JS版

// 新しく挿入するHTMLの変数を定義
var newHtml = "";

// text を1文字ずつ分割して span を追加する
text.split("").forEach(function(v) {
    newHtml += "<span>" + v + "</span>";
});

// コンテナに作ったHTMLを挿入しする
container.innerHTML = newHtml;

少し細かく書いていますが、まとめて書いちゃっても大丈夫です。

これで1文字ずつspanで囲われたと思うので、その他のJSやCSSアニメーションと連携すればOK。

プラグイン化する場合

当社の場合はプラグイン化して、使いまわせるようにしています。

// プラグイン化
$.fn.letterSpan = function() {

    // idではなくclassを使い複数設定する想定で each を使う
    $(this).each(function() {
        var text = $.trim(this.textContent),
            html = "";

        text.split("").forEach(function(v) {
            html += "<span>" + v + "</span>";
        });

        this.innerHTML = html;
    });
};

// 上記同様に #js-page-title に反映
$("#js-page-title").letterSpan();

// .js-letter-span クラスのコンテナ全てに反映
$(".js-letter-span").letterSpan();

こんな感じでプラグイン化すると使いやすくなります。

ちなみに、textをforEachで回す時に、クラスを追加したりdata-offsetやdata-delayなんていう感じで追加してあげるとさらに便利になったりもします。

三上 龍志|株式会社シンシエイト
この記事を書いた人
三上 龍志|株式会社シンシエイト
2005年からWeb制作に従事。システム開発ベンチャーでエンジニアとしてWeb開発、Webコンサルティング会社でマーケター・新規事業開発を経て2015年に当社を創業。顧客の成果に顧客よりも本気になることをテーマに、Webを通じて顧客の事業を加速させるために日々奮闘中。
マーケティングとWeb制作で
貴社の経営課題を解決します

市場調査や競合調査を始め、企業やサービスの優位性を理解した上で、UI/UX設計やコンテンツマーケティング、SEO・ネット広告を中心としたWebマーケティングを通じて、ビジネスを加速させるご提案をしています。