Edited at

JavaScriptでの要素のスタイル操作で !important を使う方法

More than 1 year has passed since last update.


はじめに

JavaScriprで要素のスタイルを普通に変更しようとしても、元々のCSSで !important 指定されている場合変更できないという問題があります。

!important を使うこと自体ナンセンスな部分がありますが、仕事で使う機会があったのでいろいろな方法を挙げてみました。

それぞれの方法を見てみます。


いろいろな方法

それぞれのメリット・デメリットも含めて。

以下のようなHTMLがあるとします。(いろいろ省略してます)


HTML

<style>

#target {
background-color: #f00 !important;
}
</style>

<div id="target" style="width: 100px; height: 100px;"></div>


この #target に対して背景色を変えてみます。


element.style.*

よく使う書き方ですが、この方法では !important を指定することはできません。


JavaScript

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

target.style.backgroundColor = '#00f';
// styleとして適用されるがこれでは優先的に下

target.style.backgroundColor = '#00f !important';
// エラーにはならないが変わらない


そもそも不可能なのでメリットもデメリットもないですね。


jQueryの .css()

万能なjQueryですが、この方法も同じように !important を指定することはできません。


JavaScript

var $target = $('#target');

$target.css('background-color', '#00f');
// styleとして適用されるがこれでは優先的に下

$target.css('background-color', '#00f !important');
// エラーにはならないが変わらない


これも不可能なのでメリットもデメリットもありません。


element.style.cssText

element.style.cssText は、要素のstyle属性で指定されているスタイルが文字列として取得でき、更に変更できるプロパティです。

これに代入して変更する方法です。


JavaScript

var

target = document.getElementById('target'),
cssText = target.style.cssText;

console.log(cssText); // "width: 100px; height: 100px;"

target.style.cssText = cssText + 'background-color: #00f !important;';
// 適用された!

// これでもいい
// target.style.cssText += 'background-color: #00f !important;';


もし既に cssTextbackground-color がある場合はスタイルが上書きされます。


メリット


  • CSSそのままの書式で書くことができる

  • 複数のスタイルを一度に書くことができる


デメリット


  • 既にstyle属性で指定されている場合、それらが上書きされないようにしなければならない

  • プロパティ名や値を変数で持ちたい場合などに文字列結合が面倒くさい


element.setAttribute()

element.setAttribute() は、要素の属性の値をセットするメソッドですが、これをstyle属性に対して使用する方法です。


JavaScript

var

target = document.getElementById('target'),
style = target.getAttribute('style');

console.log(style); // "width: 100px; height: 100px;"

target.setAttribute('style', style + 'background-color: #00f !important;');
// 適用された!


もし既にstyle属性に background-color がある場合はスタイルが上書きされます。


メリット


  • CSSそのままの書式で書くことができる

  • 複数のスタイルを一度に書くことができる


デメリット


  • 既にstyle属性で指定されている場合、それらが上書きされないようにしなければならない

  • プロパティ名や値を変数で持ちたい場合などに文字列結合が面倒くさい

  • 書式が間違っていてもそのままstyle属性の値として保持してしまう


element.style.setProperty()

element.style.setProperty() はチェインケースでスタイルを指定できるメソッドです。


JavaScript

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

target.style.setProperty('background-color', '#00f', 'important');
// 適用された!


第3引数を 'important' とすることで、!important が適用されます。(頭の感嘆符 ! は不要です)

もし、必要でない場合は第3引数を省略したり空文字や null を指定します。


メリット


  • 見た目がすっきりしている

  • キャメルケースではなくチェインケースで書けるので、書き間違いが起こらない

  • 引数ごとに分かれているので、プロパティ名や値を変数で持っている場合も扱いやすい


デメリット


  • まとめて指定できないので、適用したい分だけメソッドを書く必要がある


style要素を生成する

もう面倒だからstyle要素を作ってしまえという方法です。


JavaScript

var style = document.createElement('style');

document.head.appendChild(style);

style.textContent = '#target {background-color: #00f !important;}';
// 適用された!



メリット


  • 要素を直接いじらずにスタイルの操作ができる

  • CSSそのままの書式で書くことができる

  • 複数のスタイルを一度に書くことができる

  • JavaScriptでは取得できない擬似要素に対してスタイルを指定することができる


デメリット


  • 無駄なstyle要素が増えてしまう

  • プロパティ名や値を変数で持ちたい場合などに文字列結合が面倒くさい

  • ECMAScript 2015 のテンプレートリテラルが使用できない場合、複数行にわたる書き方が面倒くさい


CSSStyleSheet.insertRule()

style要素の CSSStyleSheet オブジェクトの CSSStyleSheet.insertRule() というメソッドを使う方法です。


JavaScript

// style属性が存在する場合はそれを利用する

var
doc = document,
style = doc.getElementsByTagName('style')[0] || doc.head.appendChild(doc.createElement('style')),
styleSheet = style.sheet;

styleSheet.insertRule('#target {background-color: #00f !important;}', styleSheet.cssRules.length);
// 適用された!

// ちなみに、ひとつのルール毎に使うメソッドなので、複数のルールを一度に指定できない
// styleSheet.insertRule('#foo {prop: value;} #bar {prop: value;}', styleSheet.cssRules.length);


CSSStyleSheet オブジェクトとは、style要素が内部で持っているCSSのルールをまとめたオブジェクトです。


メリット


  • 要素を直接いじらずにスタイルの操作ができる

  • CSSそのままの書式で書くことができる

  • ひとつのルールに複数のスタイルを一度に書くことができる

  • JavaScriptでは取得できない擬似要素に対してスタイルを指定することができる


デメリット


  • 書き方が少し複雑

  • 無駄なstyle要素が増えてしまう

  • プロパティ名や値を変数で持ちたい場合などに文字列結合が面倒くさい

  • ECMAScript 2015 のテンプレートリテラルが使用できない場合、複数行にわたる書き方が面倒くさい


おわりに

メリット・デメリットは他にもこんなのがあるよという場合は遠慮なく言ってください。