20200726のCSSに関する記事は3件です。

【初心者でもわかる】インライン要素に指定できないcss

どうも、7noteです。インライン要素に指定しても効かないcssの話。

cssってたくさんありすぎて、どれがどう反映されるのか覚えるだけでも大変なのに、
要素によっては効かないものまであるという初心者にはかなり厄介なものかなと思います。

今回はそんなcss初心者の人向けに「インライン要素には効かないcss」をまとめて紹介していきます。

インライン要素に指定しても効かないcss一覧

・ margin(の上下)

間違った記述.css
span {
    margin: 100px 0; /* ← 効きません */
}

インライン要素にはmarginの上下を指定することはできません!
親要素のブロック要素に指定するか、「display: inline-block;」「display: block;」を当ててインライン要素ではなくしてからなら効きますよ。

・ margin(auto)

間違った記述.css
span {
    margin: 0 auto; /* ← 効きません */
}

インライン要素にはmarginのautoは効きません。左右に余白をとる場合は実数値のpxなどを使うようにしましょう。

・ text-align

間違った記述.css
span {
    text-align: center; /* ← 効きません */
}

これは経験者の人でもやってしまうことあるのではないでしょうか。私はいまだにたまに間違えます。
「text-align: center;」はブロック要素に指定するものなので、「ブロック要素の中にあるコンテンツを中央揃えにしなさい」というcssなので、効きません。ちなみにinline-blickの要素にも「text-align: center;」は効きません。

・ width,height(imgタグを除く)

間違った記述.css
span {
    width: 100%; /* ← 効きません */
    height: 200px; /* ← これも効きません */
}

インライン要素に横幅と高さは指定できません。ただし例外があり、imgタグには横幅と高さを指定することができます。

主要なcssでインライン要素に効かないcssは以上ですかね。
他にも厳密にはbox-sizing: border-box;とかも横幅が効かないので同様に効かないのですが、そういうものは省きました。

まとめ

いろいろ調べたのですが、インライン要素には何が効かないのかを全部まとめてるサイトは少なかったので今回記事にしました!
このへんの話は初心者はけっこう詰まりやすいし、なかなかミスに気づかないことも多くて余計な時間をくうことになるので覚えておいて損はないです!しっかり覚えておきましょう!

おそまつ!

(コメント・質問・ソースの指摘等なんでもウェルカムです!初心者の方でも気軽に質問ください!)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

textareaの文字を色分けする(しているように見せる)方法を考えてみた

codepenやGASのエディタでは、入力された文字は次々と色分けされていきます。本記事ではそんな機能を、つまり入力された文字をそれぞれ色分けする機能を、JavaScriptのライブラリを駆使して「簡単に」再現してみようと思います。…再現と書きましたが、原理は根本的に異なるものであるということはあしからず。

sfdfg.png
サンプルのスクリーンショット
CSSを入力したら、こんな具合に色分けする。

必要なもの

  • highlight.js (JavaScriptライブラリ)
  • JavaScript/CSSについての最低限の知識

0. はじめに知っておくべきこと

ご存知の方もいらっしゃるかもしれませんが、textarea内の文字をそれぞれ別の色に変えることはできません(textareaの文字色を赤にしてSVGフィルターをかけたspanを各文字の位置に重ねるという泥臭い方法はありますが、機能性も低くハイコスト・ローリターンです)。

ではどうするのか……以下のようにすればよいのです。

  • textareaの上に「textareaではないがtextareaと同じスタイル」の要素Aを被せる
  • textareaの文字色を透明にする
  • textarea内の文章を要素Aに連動させる
  • 要素A内に収められた文章をハイライト用ライブラリ(highlight.js)でじっくり料理する

1. 要素Aを作る

ここでいう要素Aは、highlight.jsを適用できるような要素でなければなりません。つまり

sample.html
<html>
  <head>
    <link rel="stylesheet" href="style.css">

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/dracula.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/atom-one-dark.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
  </head>

  <body>

    <!--以降のHTMLの例はここから-->
    <div class="twrap">
      <textarea></textarea>

      <pre><!--要素A-->
        <code class="css"></code>
      </pre>
    </div>
    <!--ここまでのみ表示-->

    <script src="script.js"></script>
  </body>
</html>

こんな具合です。

2. 要素Aとtextareaの見た目を合わせる

まず我々には二つの道があります。

  • textareaをスクロールさせる(textareaの高さを固定する)
  • textareaをスクロールさせない(textareaの高さを可変にする)

本記事では「textareaをスクロールさせない」を選びます。

Tips あるいは失敗談
textareaをスクロールさせる方が見栄えは良いかもしれません。textareaのscroll量を要素Aに連動させるのは簡単ですし、以降の説明にある作業の多くが不要になりますからね。ですが、そのページがiPhoneからの閲覧を想定しているものならば、やめた方が良いです。iPhoneの慣性スクロールにおいては、上端あるいは下端を越えてその要素を引っ張ることができますが、そのうち上端を越える場合、JavaScript側ではscrollイベントが更新されず、そのscroll量はマイナスになってくれません。その間、textareaと要素Aの位置関係に齟齬が生まれてしまいます。

まずはtextareaと要素Aのスタイルを合致させましょう。

style.css
.twrap textarea {
  -webkit-appearance: none;
  border: 1px solid #aaa;
  border-radius: 0;
  box-sizing: border-box;
  font-size: .8rem;
  height: 100%;
  margin: 0;
  padding: 0 .25em;
  resize: none;
}
.twrap pre {
  margin: 0;
  padding: 0;
  pointer-events: none;/*要素Aを触れなくする*/
}
.twrap pre code {
  border: 1px solid transparent;
  box-sizing: border-box;
  font-size: .8rem;
  height: 100%;
  margin: 0;
  padding: 0 .25em;
  white-space: pre-wrap;
  word-break: break-all;
}

3. textareaと要素Aを重ねる

一度textareaと要素Aの位置関係を確認してみましょう。

sample.html
    <div class="twrap">
      <textarea></textarea>

      <pre><!--要素A-->
        <code class="css"></code>
      </pre>
    </div>

この場合、.twrapposition: relative;を、要素Aにposition: absolute;を設定しましょう。

style.css
.twrap {
  position: relative;/*new*/
}
.twrap textarea {
  -webkit-appearance: none;
  border: 1px solid #aaa;
  border-radius: 0;
  box-sizing: border-box;
  font-size: .8rem;
  margin: 0;
  padding: 0 .25em;
  resize: none;
}
.twrap pre {
  left: 0;/*new*/
  margin: 0;
  padding: 0;
  pointer-events: none;
  position: absolute;/*new*/
  top: 0;/*new*/
}
.twrap pre code {
  border: 1px solid transparent;
  box-sizing: border-box;
  font-size: .8rem;
  margin: 0;
  padding: 0 .25em;
  white-space: pre-wrap;
  word-break: break-all;
}

4. textarea内の文章を要素Aに連動させる&要素Aをハイライト

script.js
var textarea = document.querySelector(".twrap textarea");
var dummy = document.querySelector(".twrap pre code");

textarea.oninput = function() {
  dummy.innerText = textarea.value + "\u200b";//textareaの値の最後が改行コードだった場合に対応するためのゼロ幅スペース
  hljs.highlightBlock(dummy);
}

5. textareaと要素Aをリサイズする

これをしないと、textareaと要素Aそれぞれの文字の位置がズレます。

Googleで検索すると、textareaのリサイズについての記事が幾つか散見されます。offsetHeightとscrollHeightの違いなどをもとにwhileループで最適の大きさを求めるものなどです。スマートですね。ですが本記事の場合、もっとコストの低い良いものがあるので、それらは使いません。

ではどうするのか……要素Aのありのままの大きさを測り、それを.twrapheightとして反映すれば良いのです。そしてtextareaと要素Aにheight: 100%;をかけておけば、それらの大きさは.twrapの大きさに依存するようになります。

下準備:スタイルを合わせる

style.css
.twrap {
  position: relative;
}
.twrap textarea {
  -webkit-appearance: none;
  border: 1px solid #aaa;
  border-radius: 0;
  box-sizing: border-box;
  font-size: .8rem;
  height: 100%;/*new*/
  margin: 0;
  padding: 0 .25em;
  resize: none;
}
.twrap pre {
  height: 100%;/*new*/
  left: 0;
  margin: 0;
  padding: 0;
  pointer-events: none;
  position: absolute;
  top: 0;
}
.twrap pre code {
  border: 1px solid transparent;
  box-sizing: border-box;
  font-size: .8rem;
  height: 100%;/*new*/
  margin: 0;
  padding: 0 .25em;
  white-space: pre-wrap;
  word-break: break-all;
}
.twrap pre code.resizing {
  height: unset;/*new*/
}

リサイズ用のコードを入れる

script.js
var twrap = document.querySelector(".twrap");
var textarea = twrap.querySelector("textarea");
var dummy = twrap.querySelector("pre code");

resizeTA();

textarea.oninput = function() {
  dummy.innerText = textarea.value + "\u200b";//textareaの値の最後が改行コードだった場合に対応するためのゼロ幅スペース
  hljs.highlightBlock(dummy);
  resizeTA();
}

function resizeTA() {
  dummy.classList.add("resizing");//ありのままの大きさに戻す
  twrap.style.height = (dummy.scrollHeight + 20) + "px";//念の為に20pxほどマージンを取っている
  dummy.classList.remove("resizing");
}

6. textareaの文字色と要素Aの背景色を透明にし、highlight.jsでfont-weight: bold;にされたspanをnormalにする

Tips あるいは失敗談
本記事ではtextareaと要素Aのフォントをmonospace系にしていますが、これは等幅フォントの利便性を鑑みた結果です。monospace系は文字サイズさえ同じならば、如何な文字も、あるいは太字やイタリック体であろうと、同じ幅になるためです。いえ、そうなる予定でした。しかしiPhoneの場合、太字にすると幅が少しだけ大きくなります。PCやAndroidだと同じ幅なのに…。そんなわけで、太字も無理やり通常の太さに戻してしまっているので、必ずしもmonospace系にこだわる必要はないでしょう。

style.css
.twrap {
  position: relative;
}
.twrap textarea {
  -webkit-appearance: none;
  border: 1px solid #aaa;
  border-radius: 0;
  box-sizing: border-box;
  caret-color: #000;/*new*/
  color: transparent;/*new*/
  font-family: monospace;/*new*/
  font-size: .8rem;
  height: 100%;
  margin: 0;
  padding: 0 .25em;
  resize: none;
}
.twrap pre {
  height: 100%;
  left: 0;
  margin: 0;
  padding: 0;
  pointer-events: none;
  position: absolute;
  top: 0;
}
.twrap pre code {
  background: transparent;/*new*/
  border: 1px solid transparent;
  box-sizing: border-box;
  font-family: monospace;/*new*/
  font-size: .8rem;
  height: 100%;
  margin: 0;
  padding: 0 .25em;
  white-space: pre-wrap;
  word-break: break-all;
}
.twrap pre code.resizing {
  height: unset;
}
.twrap pre code span {
  font-weight: normal;
}

あとは各要素の大きさに影響を与えない範囲でデザインすれば完成です。

おわりに

iOSを開発されている方々に一言物申したいですね。iOSには面白い機能がたくさんあり、彼らの独創性・発想力、目を見張るものがあると思います。利便性を謳いたくなるのも分かります。ですがその前に、計画性と協調路線の存在にしっかりと目を向けてもらいたいですね。ここまでで挙げた通り、iOSのせいで余計な回り道をさせられています。この例に限った話ではないです。独自路線を突っ走り過ぎると嫌われますよ。

サンプル

http://topia.wdfiles.com/local--code/css-parser-1/1

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初心者によるプログラミング学習ログ 382日目

100日チャレンジの382日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。
100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
382日目は、

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む