HTML
JavaScript
0
どのような問題がありますか?

投稿日

更新日

HTMLの文章を行ごとに分割して装飾をつける

おら、アクセシビリティのことはよくわかんねぇんだけど、
とりあえず見た目は動いたぞ。

test.html - Google Chrome 2022_04_22 23_49_35.png

<html>
  <head>
    <style>
      #tmp-box {
        position: absolute;
        left: -100000px;
        white-space: pre-line;
      }
      #text-box > div {
        border-bottom: dashed 1px #aaa;
      }
    </style>
  </head>
  <body>
    <div id="tmp-box"></div>
    <div id="text-box"></div>
    <script>
      const text =
        '素早い茶色の狐はのろまな犬を飛び越える。\n素早い茶色の狐はのろまな犬を飛び越える。素早い茶色の狐はのろまな犬を飛び越える。';
      const tmpBox = document.getElementById('tmp-box');
      const textBox = document.getElementById('text-box');
      // 画面外に逃がしたtmp-boxに、描画領域の幅を設定する
      tmpBox.style.width = textBox.clientWidth + 'px';
      // 一文字ずつspanでつつむ
      const chars = text.split('').map((c) => {
        const span = document.createElement('span');
        span.textContent = c;
        return span;
      });
      // 仮想DOM使わないと重くなる
      const div = document.createElement('div');
      div.append(...chars);
      tmpBox.append(div);
      // 行ごとのdivに変換
      const lines = chars
        .reduce((prev, span) => {
          const lastLine = prev[prev.length - 1];
          // offsetTopの値が変わっていれば改行しているはず
          if (lastLine && lastLine[0]?.offsetTop === span.offsetTop) {
            lastLine.push(span);
          } else {
            prev.push([span]);
          }
          return prev;
        }, [])
        .map((line) => line.map((c) => c.textContent).join(''))
        .map((line) => {
          const div = document.createElement('div');
          div.textContent = line;
          return div;
        });
      textBox.append(...lines);
    </script>
  </body>
</html>

ユーザー登録して、Qiitaをもっと便利に使ってみませんか。
  1. あなたにマッチした記事をお届けします
    ユーザーやタグをフォローすることで、あなたが興味を持つ技術分野の情報をまとめてキャッチアップできます
  2. 便利な情報をあとで効率的に読み返せます
    気に入った記事を「ストック」することで、あとからすぐに検索できます
sujoyu
お絵かきが好きなプログラマ

コメント

やりたいことは
文字列1文字ずつのspan要素1行づつのdiv要素 へ順次変換
と解釈して、

<html>
  <head>
    <style>
      #tmp-box {
        display: none;
      }
      #text-box > div {
        border-bottom: dashed 1px #aaa;
      }
    </style>
  </head>
  <body>
    <div id="tmp-box"></div>
    <div id="text-box"></div>
    <script>
      const
        text = '素早い茶色の狐はのろまな犬を飛び越える。\n素早い茶色の狐はのろまな犬を飛び越える。素早い茶色の狐はのろまな犬を飛び越える。',
        tmpBox = document.getElementById('tmp-box'),
        textBox = document.getElementById('text-box');

      tmpBox.innerHTML = text.split('').map(s => `<span>${s}</span>`).join('');
      textBox.innerHTML = tmpBox.textContent.split('\n').map(s => `<div>${s}</div>`).join('');
    </script>
  </body>
</html>

みたいな感じでは駄目でしょうか。

0
どのような問題がありますか?
あなたもコメントしてみませんか :)
ユーザー登録
すでにアカウントを持っている方はログイン
記事投稿イベント開催中
新人プログラマ応援 - みんなで新人を育てよう!
~
データに関する記事を書こう!
~
0
どのような問題がありますか?
ユーザー登録して、Qiitaをもっと便利に使ってみませんか

この機能を利用するにはログインする必要があります。ログインするとさらに下記の機能が使えます。

  1. ユーザーやタグのフォロー機能であなたにマッチした記事をお届け
  2. ストック機能で便利な情報を後から効率的に読み返せる
ユーザー登録ログイン
ストックするカテゴリー