初心者向け!疑似要素入門
疑似要素使い方やのcontentプロパティにJavaScriptからアクセスする方法をご紹介します。
更新:
環境:windows10/Microsoft Edge/VS Code
PREPARATION
想定する読者と前提条件
基本的なパソコン操作ができること。HTML、CSS及びJavaScriptの基礎程度の知識が必要です。
START
疑似要素とは?
CSSの疑似要素は、セレクターに付加するキーワード(::afterや::before)で、セレクターで指定した要素の特定の部分にスタイル付けできるようにするものです。 ::beforeは選択した要素の最初の子要素として、::afterは選択した要素の最後の子要素として擬似要素を作成します。 これらで追加した疑似要素は、contentプロパティを使用して、要素に文字や画像等の内容を追加することができます。
contentプロパティは、::afterと::before疑似要素でしか利用することはできません。
CSS3から ::(二重コロン付き) が導入されました。 CSS2で使用されている :(コロン付き) も使用できます。
CSS3 → ::before / CSS2 : before
どんな事ができるの?
ここでは、疑似要素でどのようなことができるのか詳しく見ていきましょう。
content:normal;は、content:none;と同じ意味であり、疑似要素は描画されません。
文字を追加する
最も基本的な利用法は、疑似要素に文字列を追加する方法です。contentプロパティに表示したい文字列を記述します。 下記の例では、::beforeを用いていますので、要素の最初に追加されます。
li::before {
content: "→"; /* contentプロパティに表示したい文字列を記述します。 */
}
<ul>
<li>小麦粉 180g</li>
<li>アーモンドプードル 40g</li>
<li>ヘーゼルナッツパウダー 20g</li>
</ul>
- 小麦粉 180g
- アーモンドプードル 40g
- ヘーゼルナッツパウダー 20g
画像を表示する
疑似要素で画像を表示させることも可能です。 ただし、一般的に擬似要素は、display:inline、height:auto、width:autoとして定義されます。
h2.rep::before {
content:url(./images/c-rep.png);
}
<h2 class="rep">リピート</h2>
リピート
画像サイズが適切でない場合、上記のように画像が大きく表示されてしまいます。 画像サイズの調整方法はいくつかあります。まず1つ目の方法は、transform: scale(x)を用いて縮小します。 位置調整をするため、親要素にdisplay:flexを指定、transformを有効化するために擬似要素にdisplay:blockを指定しています。
h2.rep{
font-size: 1rem;
height: 1rem;
display: flex;
flex-direction: row;
align-content: center;
justify-content: flex-start;
align-items: center;
flex-wrap: nowrap;
}
h2.rep::before {
content: url(./images/getcomputedstyle/c-rep.png);
width: 50px;
height: 50px;
display: block;
transform: scale(0.4);
}
<h2 class="rep">リピート</h2>
リピート
もう1つの方法としては、画像を背景画像として設定し、background-sizeをcontain、coverを 設定することで表示領域サイズに収まるように拡大縮小します。
h2.rep{
font-size: 1rem;
height: 1rem;
display: flex;
flex-direction: row;
align-content: center;
justify-content: flex-start;
align-items: center;
flex-wrap: nowrap;
}
h2.rep::before {
content: "";
background-image:url(./images/getcomputedstyle/c-rep.png);
background-size: cover;
width: 20px;
height: 20px;
display: block;
}
<h2 class="rep">リピート</h2>
リピート
htmlの属性を表示する
attr()は、要素の属性の値を文字列として取得することができます。属性が存在しない場合は、空文字列が返されます。 htmlのdata-*属性と組み合わせることで任意の文字列をcontentに設定可能です。
p::before {
content: attr(data-hoge); /* contentプロパティに表示したい文字列を記述します。 */
}
<p data-hoge="○">小麦粉 180g</p>
小麦粉 180g
連番を振る(1)
疑似要素そしてCSSのcounterプロパティを用いて番号を割り当てることができます。
body {
counter-reset: section;/* カウンターの初期化(0に設定)*/
}
h2{
counter-increment: section;/* h2が登場する毎にカウンターを1加算*/
}
h2::before {
content: counter(section) ". "; /* カウンターを表示 */
}
<h2>クッキーの材料</h2>
<h2>クッキーの記事作り</h2>
<h2>クッキーの焼き方</h2>
クッキーの材料
クッキーの記事作り
クッキーの焼き方
連番を振る(2)
counterは複数用いることができます。1-1、1-2、2-1等、見出しの階層構造を意識した連番を割り当てることも可能です。 counter-resetのタイミングに注意してください。
body {
counter-reset: section1;
counter-reset: section2;
counter-reset: section3;
}
section.chapter{
counter-increment: section1;
}
section.chapter h2{
counter-reset: section2;
}
section.chapter h3{
counter-reset: section3;
counter-increment: section2;
}
section.chapter h4{
counter-increment: section3;
}
section.chapter h2::before {
content: "第" counter(section1) "章 " "\A";/* \Aは改行コードを示します。 */
white-space: pre ; /* 改行を有効にするためwhite-spaceをpreに設定 */
}
section.chapter h3::before {
content: counter(section1) "-" counter(section2) " ";
}
section.chapter h4::before {
content: counter(section1) "-" counter(section2) "-" counter(section3) " "
}
<h1>タイトル</h1>
<section class="chapter">
<h2>タイトルh2</h2>
<h3>タイトルh3</h3>
<h4>タイトルh4</h4>
<h4>タイトルh4</h4>
<h3>タイトルh3</h3>
<h4>タイトルh4</h4>
<h4>タイトルh4</h4>
</section>
<section class="chapter">
<h2>タイトルh2</h2>
<h3>タイトルh3</h3>
<h4>タイトルh4</h4>
<h4>タイトルh4</h4>
<h3>タイトルh3</h3>
<h4>タイトルh4</h4>
<h4>タイトルh4</h4>
</section>
タイトル
タイトルh2
タイトルh3
タイトルh4
タイトルh4
タイトルh3
タイトルh4
タイトルh4
タイトルh2
タイトルh3
タイトルh4
タイトルh4
タイトルh3
タイトルh4
タイトルh4
その他の設定について
contentプロパティには、その他にも様々な値を設定可能です。詳しく見ていきましょう。
- string
-
最初の例のように、文字列を指定することができます。文字は、ダブルクォーテーションまたはシングルクォーテーションで囲む必要があります。 ""を指定すると空文字列となり、文字列は描画されませんが、CSSで装飾を施すことができます。
- uri
-
外部リソース(画像など)を指定するURIを利用できます。
一般的な記述方法はurl("http://hoge.com/hoge.png")です。 - gradient
-
グラデーションを生成することができます。linear-gradient(#e66465, #9198e5)等、様々なグラデーションを指定できます。
- element
-
要素から生成されたimageを設定できます。要素が変更されると、自動的に更新されます。canvasなどで利用されます。element(#hoge)等で指定
- attr
-
要素の属性の値を文字列として返します。属性が存在しない場合は、空文字列が返されます。
- counter
-
先程の例のように、counter()またはcounters()の2つの異なる関数で指定し、連番を付与することができます。 カウンターを使用するには、必ず counter-reset プロパティで値を初期化する必要があります。カウンターの値は counter-increment で増加させることができます。
/* 基本的な構文 */ counter-reset:section1 /* section1を0に初期化。初期値は0です。 */ counter-reset:section1 10 /* section1を10に初期化。初期値を設定できます。 */ counter-reset:section1 1 section2 2 }/* section1を1、section2を2に初期化。 */ counter-increment: section1; /* これは1加算 */ counter-increment: section1 - 1; /* これは1減算 */ counter-increment: section1 - 2; /* これは2減算 */ counter-increment: section1 section2; /* これはsection1とsection2を加算 */ counter-increment: section1 section2 + 2; /* これはsection1を加算、section2を2加算 */ counter-increment: section1 section2 + 2 section3; /* これはsection1,section3を加算、section2を2加算 */ /* ネストしたカウンター */ ol { counter-reset: section } li::before { content: counters(section, "-") " "; counter-increment: section } <ol> <li>item</li> <!-- 1 --> <li>item <!-- 2 --> <ol> <li>item</li> <!-- 2-1 --> <li>item</li> <!-- 2-2 --> <li>item <!-- 2-3 --> <ol> <li>item</li> <!-- 2-3-1 --> <li>item</li> <!-- 2-3-2 --> </ol> </li> <li>item</li> <!-- 2-4 --> </ol> </li> <li>item</li> <!-- 3 --> </ol>
JavaScriptからのアクセス方法
ここからは、JavaScriptを用いて疑似要素にアクセスする方法を見ていきましょう。 一般的なHTML要素は、querySelectorやquerySelectorAllを用いてアクセスすることができますが、疑似要素にはアクセスできません。
疑似要素は実際の要素ではないため、CSSスタイルにアクセス可能なgetComputedStyle()を用いてアクセスする必要があります。
getComputedStyle
getComputedStyleを用いたアクセス方法を見ていきましょう。getComputedStyleは、指定された要素のCSSプロパティの値を含むオブジェクトを返します。 取得できるCSSの値は、最終的にその要素に適用されている値を返すことになります。
/* 基本的な構文 */
/* pseudoEltには、"::after"や"::before"を指定します。 */
let style = window.getComputedStyle(element [,pseudoElt]);
- element
-
疑似要素を作成した要素を指定します。
- pseudoElt
- 疑似要素を指定する場合は、"::after"または"::before"を用いて疑似要素のスタイルにアクセスすることができます。 通常の要素のスタイルを取得する場合には、記述不要です。(CSS2指定の:afterや:beforeでも可能)
- 戻り値
- CSSStyleDeclarationオブジェクトを返します。
let element = document.querySelector("#el");
/* ::beforeを取得する */
let style = window.getComputedStyle(element, "::before");
/* ::afterを取得する */
let style = window.getComputedStyle(element, "::after");
/* elementのスタイルを取得する */
let style = window.getComputedStyle(element);
contentプロパティを取得
CSSStyleDeclarationオブジェクトからcontentプロパティにアクセスする方法
let element = document.querySelector("#el");
/* ::beforeを取得する */
let style = window.getComputedStyle(element, "::before");
let content = style.content; //これでcontentの値を取得。
/* getPropertyValueを使用したアクセス方法 */
let content = style.getPropertyValue("content");
contentプロパティを書き換える方法
CSSStyleDeclarationオブジェクトには、setProperty()があり一般的なスタイルは書き換え可能ですが、 contentプロパティの書き換えは行うことができません。
contentプロパティの書き換えを行う方法は、新たなCSSを追加し、contentプロパティを再定義することで 設定を上書きします。ここでは、addStylesheetRules()関数を定義し、contentプロパティを上書きする方法をご紹介します。
let addStylesheetRules = (selector, rules) => {
const styleEl = document.createElement('style');
let property ='';
let styleSheet = null;
document.head.appendChild(styleEl);
styleSheet = styleEl.sheet;
for (let i = 0; i < rules.length; i += 1) {
let prop = rules[i];
property += `${prop[0]}: ${prop[1]};`;
}
styleSheet.insertRule(`${selector}{${property}}` , styleSheet.cssRules.length);
};
/* h3::after疑似要素のcontentプロパティ及びカラーを変更する場合 */
/* contentプロパティのダブルクォーテーションは残す必要があるため、注意が必要です。*/
addStylesheetRules('h3::after', [['content','"変更完了"'],['color','#f0f']]);
または、attrでHTMLの属性値を参照している場合、HTMLの属性値を変更することで、疑似要素を書き換えることも可能です。