LoginSignup
7
7

More than 3 years have passed since last update.

Summernoteのエディタ「内」に外部CSSを適用する

Last updated at Posted at 2019-07-05

結論 LESSを使う

単なるCSSファイルを読み込む場合もLESSファイルとして読み込む必要があります。
でなければ、スコープ内に限定したCSS適用が出来ません

/admin/css/import.less
.note-editable {
  @import (less) "/css/reset.css";
  @import (less) "/css/base.css";
  @import (less) "/css/styles.css";
}
/admin/index.php
<link rel="stylesheet" type="text/css" media="all" href="/admin/plugins/summernote/summernote-bs4.css">

<script type="text/javascript" charset="utf-8" src="/admin/plugins/jquery/jquery.min.js"></script>
<script type="text/javascript" charset="utf-8" src="/admin/plugins/bootstrap-4.1.3/js/bootstrap.bundle.min.js"></script>
<script type="text/javascript" charset="utf-8" src="/admin/plugins/summernote/summernote-bs4.js"></script>

<!-- LESSファイルを読み込む際は rel="stylesheet/less" と書くことに注意 -->
<link rel="stylesheet/less" type="text/css" media="all" href="/admin/css/import.less" />
<script src="//cdnjs.cloudflare.com/ajax/libs/less.js/3.9.0/less.min.js" ></script>

<scirpt>
$(function(){
  $('#sample').summernote();
});
</scirpt>

<textarea name="sample" id="sample"></textarea>

背景

  • 管理画面にSummernoteを使ってWYSIWYGエディタを実装した
  • WYSIWYGエディタで入力したHTMLデータはDBに格納され、PHPなどを経由してユーザ向け画面にHTMLとして描写される
  • ユーザー向け画面は、デザイナーとか、自分以外の人間が書いたCSSが適用される
  • 管理画面のWYSIWYGエディタでも、出来る限りユーザ向け画面と同じ見た目でHTMLが記述できるようにしたい

やりたいこと

  • Summernoteのエディタ「内」に、ユーザ向け画面のCSS(外部CSS)を適用したい

何が問題か

  • ユーザ向け画面のCSSは今後も変更される可能性があり、自分では編集できない
  • SummernoteのHTML表現は、元のHTML内部にdivなどの要素を追加する形である
    • そのまま外部CSSを適用すれば、WYSIWYGエディタの外側である管理画面にもCSSの影響が出て、レイアウト崩れが発生

考え方

  • SummernoteのWYSIWYGエディタ「内」とは、div.note-editable の中のことである
  • このdiv.note-editableの中にだけ、次のような形でCSSが適用できればそれで要件は達成できる
.note-editable h1 {
  font-size: 24px;
}

.note-editable h2 {
  font-size: 20px;
}

.note-editable h3 {
  font-size: 18px;
}

.note-editable .hoge ...

ユーザ向け画面のCSSは今後も事前の予告なく書き換わることが十分に考えられるため、
別名でコピーして全部のセレクタ―に.note-editableを付け加えまくるのは
メンテナンス性が悪すぎますし、そもそもやりたくありません。

ユーザ向け画面のCSSを、特定のセレクタの下にimportすることができれば、
ユーザ向け画面のCSSがいくら書き換わろうが、管理画面側(私側)は一切手を動かさないで済みます。
この願いをかなえてくれるのが、LESSでした。

余談

TinyMCEならば、content_cssというプロパティを用いて、エディタ内に外部CSSを適用できます。
TinyMCEはiframeで動いているため、iframe内にCSSを適用してもその外側(管理画面自体)にはレイアウト崩れなどの影響がありません。
もしこれを読んでいるあなたがまだ、WYSIWYGエディタを実装していないのであれば、TinyMCEを利用することをオススメします。。

参考にしたURL

追記

デザイナーから提供された外部CSSが次のような形で、
特定のクラスの配下にあることを前提としたものだった場合。

.entry h1 {
  font-size : 24px;
}

.entry h2 {
  font-size : 20px;
}

順当に考えれば、次のようにSummernoteエディタ上で
そのクラスで囲んだHTMLを用意すれば、期待したレイアウトで表示されるはずです

<div class="entry">
  <h1>h1テキスト</h1>
  <h2>h2テキスト</h2>
</div>

ですが、オペレータにおまじないで毎回divを書いてくれと言うのはヒューマンエラーのもと。
それに、DBに親要素の情報まで格納するのは今後、サイトリニューアルがあった時に足枷になりかねない。

ので、おまじないナシで、オペレータには次のような入力をさせて、
ユーザ向け画面のCSSを表示したいと思います。

<h1>h1テキスト</h1>
<h2>h2テキスト</h2>

考え方

SummernoteのHTML構成は次のような形になっています

<div class="note-editing-area">
    <div class="note-placeholder" style="display: none;">
        placeholder text is here
    </div>
    <div class="note-handle">
        <div class="note-control-selection" style="display: none;">
            <div class="note-control-selection-bg"></div>
            <div class="note-control-holder note-control-nw"></div>
            <div class="note-control-holder note-control-ne"></div>
            <div class="note-control-holder note-control-sw"></div>
            <div class="note-control-sizing note-control-se"></div>
            <div class="note-control-selection-info"></div>
        </div>
    </div>
    <textarea aria-multiline="true" class="note-codable" role="textbox"></textarea>
    <div aria-multiline="true" class="note-editable card-block" contenteditable="true" role="textbox">
        <h1>h1テキスト</h1>
        <h2>h2テキスト</h2>
    </div>
</div>

LESSによって今、次のような形で外部CSSが表現されています

.note-editable .entry h1 {
  font-size : 24px;
}

.note-editable .entry h2 {
  font-size : 20px;
}

.note-editableに外部CSSの親要素のクラス名を付与し、
次のようなCSS組みが出来れば、要件は達成できそうです

.note-editing-area .entry h1 {
  font-size : 24px;
}

.note-editing-area .entry h2 {
  font-size : 20px;
}

実装

LESSの記述を変更

/admin/css/import.less
.note-editing-area {
  @import (less) "/css/reset.css";
  @import (less) "/css/common.css";
  @import (less) "/css/category.css";
}

エディタに親要素のクラスを付与

/admin/js/admin.js
$(function(){
  $(".note-editable").addClass("entry");
});

さらに追記

一応Summenoteの公式にもこの件でチケット起票していたのですが、
公式には対応する手段はないとのことでクローズされました(絶望)

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7