またしてもいまさらだけど・・・。
色々やっていて、あれっ!と、想定したとおりに作用していないのでは?と感じることがあったので、そのあたりをしっかり認識しておくために、Javascript .style.cssText の再確認。

javascript での style 設定はインライン

いまさらではの復習。
HTML の各要素のスタイルを設定するには、外部スタイルシートのファイルをロードするか、<head></head> タグ内に <style></style> タグを使用して記述する。
そして、もうひとつは HTML の各要素のタグ内に直接 style=”” として記述する、これがいわゆるインラインという方式。
同じ要素の同じプロパティに対して、複数の場所に重複して設定が記述された場合は、その要素により近いところで書かれたものか、後から読み込まれた値が上書きされて、そのスタイルが優先されるということ。
後は、Javascript .style. を使用して動的に設定する方法もあり、これもインラインということになる。

で、その Javascript における .style. がこのページの本題となる。
普通に使っている基本的なやり方はといえば、各プロパティを個別にひとつづつ指定するもので、

const target = document.getElementById( 'target' );

target.style.width = '80%';
target.style.height = '400px';
target.style.backgroundColor = 'blue';
JavaScript
CopyExpand

と、言う感じ。
これは連想配列などを使えば(速度的には連想配列はあまり使いたくないというこだわりもあるけれど・・・)こんな書き方でもいいわけで。

const target = document.getElementById( 'target' ),
    styles = {
        width:'80%',
        height:'400px',
        backgroundColor:'blue'
    };

for ( const key in styles ) {
    target.style[ key ] = styles[ key ];
}
JavaScript
CopyExpand

まぁ、私事ながら連想配列を使いたくないということなら、二次元配列にするとか配列を2つにするとかしてループさせれば同じこと。まぁ、でもこれ、実際にやってみたけれど、予想に反して、速度的にはほとんど差はなかった。このページ→ 「JavaScript をわずかでも速くするために」 で色々試してみた時は、連想配列を使うと極端に遅くなってしまったのだけれど( 私は Firefox 使いなもので )。Chrome での for-in は速かったが、Firefox でも変わらないというのは、Firefox でも for-in において Chrome ばりに改善されたということなのだろうか?
なんにしても、実際やってみたところほとんど差は無かったので、どれでも好きなようにやれば良いのでは、と。

そしていよいよというかもう一つの書き方。
各プロパティをまとめて一文で書ける一括指定パターンの style.cssText

const target = document.getElementById( 'target' ),

target.style.cssText = 'width:80%;height:400px;background-color:blue;';
JavaScript
CopyExpand

一行ですむし一見さっぱりしているようにも見える。
書き方にちょっと違いがあって、前者はプロパティ名をケバブケース( backgroundColor )で指定するのに対して、cssText では本来の css と同様、キャメルケース( background-color )で指定すること。と、それぞれの設定には最後に ; が必要ってことかな。

style.cssText= はそれ以前のインライン設定をリセットしてしまう

Javascript においてのこの二通りの書き方は、両方ともにインラインとなる。
そして、cssText において重要なるポイントは、”.style.cssText = ” のように ”=” だけで設定した場合は、それ以前にその要素においてインラインで設定されたものはすべて無効とされてしまうということである。
改めて確認しておくと、インラインでの設定というのは、HTML の各要素のタグにおいて style=”” で設定したものと、Javascript において .style. を使用して設定したスタイルということ。
逆にいうと、<head></head> タグ内で <style></style> タグにて設定されたものと、ロードされた外部スタイルシートにおいて設定されたものは、”.style.cssText = ” のように “=” だけで設定されても、既存の設定が変更され上書きされない限り、キープされ存続されるということである。
これに対し、プロバティをひとつづつ指定する個別パターンは、インラインであろうが、既存する他のプロパティには影響をあたえず、その時指定したものだけが上書き変更される。

ということは、既存の設定を維持しておきたい場合に、cssText は使いづらいということになるが、そんなことはなくて、”.style.cssText += ” という具合に ”+=” にすれば既存の設定も維持したまま新しい設定を適用してくれる。が、ちょっと気になる点もあることにはあるのだけれど・・・、と、それは後ほど。
で、アウトライン?(でいいのか?)とインラインで指定したものがどうなるかということを実際に試してみると。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">

<style type="text/css">
    #maincontents{
        position:relative;
    }
    #test{
        position:relative;
        width:100px;
        height:100px;
        margin:20px auto 30px auto;
        font-size:0.8em;
        background:lavender;
    }
</style>

</head>
<body>
	<div id="maincontents">
        <div id="test" style="padding:10px;font-size:1.5em;background:lightgreen;">test box</div>
    </div>
</body>
<script type="text/javascript">
( function() {
    function Gi( name ) {
        let ans = null;

        ans = document.getElementById( name );
        return ans;
    }

    const tar = Gi( 'test' );

    setTimeout( () => {
        tar.style.background = 'plum';
        // この時点で有効なスタイル
        // position:relative;
        // width:100px;
        // height:100px;
        // margin:20px auto 30px auto;
        // padding:10px;
        // font-size:1.5em;
        // background:plum;
    }, 1000 );

    setTimeout(() => {
        tar.style.cssText = 'border:dotted red 1px;';
        // この時点で有効なスタイル
        // position:relative;
        // width:100px;
        // height:100px;
        // margin:20px auto 30px auto;
        // font-size:0.8em;
        // background:lavender;
        // border:dotted red 1px;
    }, 2000 );

    setTimeout( () => {
        tar.style.borderRadius = '50%';
        // この時点で有効なスタイル
        // position:relative;
        // width:100px;
        // height:100px;
        // margin:20px auto 30px auto;
        // font-size:0.8em;
        // background:lavender;
        // border:dotted red 1px;
        // border-radius:50%;
    }, 3000 );

    setTimeout( () => {
        tar.style.cssText += 'border:ridge silver 3px;';
        // この時点で有効なスタイル
        // position:relative;
        // width:100px;
        // height:100px;
        // margin:20px auto 30px auto;
        // font-size:0.8em;
        // background:lavender;
        // border:ridge silver 3px;
        // border-radius:50%;
    }, 4000 );

    setTimeout( () => {
        tar.style.cssText = 'position:relative;';
        // この時点で有効なスタイル(初期化: アウトライン設定状態)
        // position:relative;
        // width:100px;
        // height:100px;
        // margin:20px auto 30px auto;
        // font-size:0.8em;
        // background:lavender;
    }, 5000 );
}());
</script>
</html>
HTML
CopyExpand

で、左から右へ、という具合になるわけです。(モバイル等狭い画面ではつぶれて表示されてしまうかも)

test box
test box
test box
test box
test box
test box

個別にひとつづつ書くのも、それを連想配列か配列をつかってループさせるのも、cssText で一括で設定するのも、ベンチで試してみても速さ的にはそんなに違いはなく、強いて言えば、cssText が頭ひとつ分出ているかな?という具合だった。ただし要注意なのは、それは ”=” での場合だけに限られる。複数のスタイルを既存の設定を残しつつと、”+=” を使用すると cssText での設定は俄然、遅くなってしまう。ベンチでは倍以上、内容によっては数倍も遅くなってしまうこともあった。
「JavaScript をわずかでも速くするために」のページでお世話になった「O’REILLY High Performance JavaScript 」の本にも、「Javascript からスタイル設定を変更する場合、それが複数ある場合に、それぞれ一つづつを変更していくのではなく、style.cssText によってまとめて処理をした方が再描画と再配置の回数を減らすことができてパフォーマンス的に有効。」とのことが書いてあったが、現在のところ、それは ”=” を使った時だけのことに限られるようだ。

と、いうのは、そもそもこのことにちょっと疑問を持ったことがあったからである。
ある要素を移動させながら、その背景画像の位置も繰り返し変更させてアニメーションを作っていたところ、Firefox ( 89.0b11 )では何の異常もなかったものが、いざ Chrome ( 90.0.4430.212 ) においてはチラチラとノイズのようなものが入ってしまったのである。で、これの原因というのは、ディベロッパーツールを開いていたからなのである。それによって負荷が大きくなってしまったのか、ディベロッパーツールを閉じてしまえば出ることはなかった。
ふと、cssText で書いていたものを個別パターンに変更してみたところ、そのチラチラノイズは出なくなったのである。この事があって、見たところは悪いけれど、実は個別パターンでたらたらとリストを並べた方が処理が速いのではないか、と、いずれ試してみる必要があると思っていたわけで、やっぱりということになった。

と、いうことで、まとめてみると。

  • Javascript からの初めての設定の場合とか、インラインで設定した既存の設定が全く必要の無い時には、迷わず cssText を使用する。”=” で何の問題もない場合に限るということ。
  • それ以外の場合、設定する項目が一つであれ、多数であれ、個別パターンで一つ一つ設定する。cssText での ”+=” は使わない。項目が多い場合、速度的にはほとんど差がないので、連想配列を使ってループさせるのもあり。関数化しておけば、見た目的にもこちらのほうが好感がもてそう。

こんなものでいいのではないだろうか。id の要素専用で速度重視でよけいな判別分岐とかは一切いれない。エラー対策もなし。とにかくシンプルに。スタイル設定は連想配列にして引数で渡す。

function SSi( target, prop ) {
	const tar = document.getElementById( target );

	for ( const key in prop ) {
		tar.style[ key ] = prop[ key ];
	}
}

SSi( 'target', { visibility:'visible', fontSize:'1.1em', opacity:0, transition:'opacity 1.5s' } );
JavaScript
CopyExpand

Leave a Reply!

JavaScript is necessary to send a comment.
You can edit and delete your comment if you input a edit key.
Edit key is necessary for attesting you when you edit and delete it.
The tag of HTML cannot be used in comment.
When you comment for the first time, it is displayed after the approval of the administrator.
Because I cannot speak English so much, it takes time to answer.
Required fields are marked *.

※Please enter more than 5 characters only alphabets.
※Edit or delete are possible for 2000 days after approval.

*

♠Simplistic Comment User Editable v4.0

♠When visitors leave comments on the site this site collect the data shown in the comments form, and also the visitor’s IP address and browser user agent string to help spam detection.
♠This site does not use cookie when visitors leave comments and commenter edit comment.
♠This site uses Akismet to reduce spam. Learn how your comment data is processed.

Comments feed

Trackback URL : https://strix.main.jp/wp-trackback.php?p=166234

Sanbanse Funabashi

Top

スクロールさせるか画像をクリックすると元に戻ります。