web-dev-qa-db-ja.com

JavaScript / jQueryを使用したCSSクラスプロパティ値のオンザフライでの変更

私はこれまでに解決策を見つけることができなかったユニークな状況に遭遇しました:値をCSSスタイルに動的に割り当てる。 jQueryを使用して要素に幅、高さなどを割り当てる方法は知っていますが、実際にスタイルシートで定義されている値を変更して、動的に作成された値を複数の要素に割り当てることを試みています。

私が構築しているのは、ビューポート全体を占める画像のスライドショーです。画像の幅、高さ、およびサイズ変更時の左プロパティを再計算して、画像が常に中央に配置され、ビューポートがそれよりも高い場合を除き、高さよりも幅を優先します幅が広い(サイズ変更はページをリロードせず、画像のサイズを変更する関数を起動するだけです)。

1つの画像で正常に機能するようになりました。現在、これらの3つの項目をすべての画像に個別に指定することなく、スライドショーのすべての画像にそれらのプロパティ値を割り当てる最良の方法を決定しようとしています。

私の質問:

クラスのプロパティの値をその場で変更できますか?私は答えがそこにあると確信しています、おそらく検索で正しい用語を使用していないだけです。問題をうまく説明できたと思います。 TIA。

51
JPN

ここでの回答のいくつかに反して、Javascriptを使用してスタイルシート自体を編集することは可能であるだけでなく、パフォーマンスも向上します。単に$('.myclass').css('color: red')を実行すると、セレクターに一致するすべての項目をループし、スタイル属性を個別に設定します。これは非常に非効率的で、数百の要素がある場合、問題が発生します。

アイテムのクラスを変更することは良い考えですが、N個のアイテムの属性を変更するという点で、同じ問題を抱えています。より良い解決策は、1つの親アイテムまたは少数の親アイテムのクラスを変更し、cssの「カスケード」を使用してターゲットアイテムをヒットすることです。これはほとんどの状況で役立ちますが、すべてではありません。

場合によっては、多くのアイテムのCSSを動的なものに変更する必要があります。そうしないと、少数の親を叩いてそれを行う良い方法がありません。スタイルシート自体を変更するか、既存のcssを上書きする小さな新しいスタイルシートを追加することは、アイテムの表示を変更する非常に効率的な方法です。 DOMと1か所でやり取りするだけで、ブラウザーはこれらの変更の展開を非常に効率的に処理できます。

jss は、JavaScriptからスタイルシートを直接編集しやすくするためのライブラリの1つです。

28
user748221

DemoIE demo

次の機能を使用できます。

function setStyle(cssText) {
    var sheet = document.createElement('style');
    sheet.type = 'text/css';
    /* Optional */ window.customSheet = sheet;
    (document.head || document.getElementsByTagName('head')[0]).appendChild(sheet);
    return (setStyle = function(cssText, node) {
        if(!node || node.parentNode !== sheet)
            return sheet.appendChild(document.createTextNode(cssText));
        node.nodeValue = cssText;
        return node;
    })(cssText);
};

機能

  • この関数はVanilla-jsで記述されているため、jQueryの代替よりもパフォーマンスが優れています
  • setStyleの最初の呼び出しの後に1つのスタイルシートが作成されるため、呼び出さない場合、スタイルシートは作成されません。
  • 同じスタイルシートは、次のsetStyleの呼び出しに再利用されます
  • この関数は、追加したCSSの束に関連付けられたノードへの参照を返します。そのノードを2番目の引数として再度関数を呼び出すと、古いCSSが新しいCSSに置き換えられます。

var myCSS = setStyle('*{ color:red; }');
setStyle('*{ color:blue; }', myCSS); // Replaces the previous CSS with this one

ブラウザのサポート

少なくとも、IE9、FF3、Chrome 1、Safari 4、Opera 10.5。

IE version もあります。これは、最新のブラウザとIEの古いバージョンの両方で動作します! (IE8およびIE7で動作しますが、IE6をクラッシュさせる可能性があります)。

22
Oriol

いい質問です。ここでの答えの多くは、あなたが尋ねていたものと直接矛盾する解決策を持っていました

「jQueryを使用して幅、高さなどを要素に割り当てる方法を知っていますが、実際にスタイルシートで定義されている値を変更して、動的に作成された値を複数の要素に割り当てることを試みています。

jQuery .cssスタイル要素インライン:物理的なCSSルールを変更しません!これを行うには、Vanilla JavaScriptソリューションを使用することをお勧めします。

document.styleSheets[0].cssRules[0].cssText = "\
     #myID {
         myRule: myValue;
         myOtherRule: myOtherValue;
     }";

この方法では、インラインスタイルを追加するのではなく、スタイルシートのCSSルールを設定しています。

お役に立てれば!

18
Jace Cotton

@benvieが言ったように、jQuery.css(セット内のすべての要素をループする)を使用するよりもスタイルシートを変更する方が効率的です。また、関数が呼び出されるたびに新しいスタイルをヘッドに追加しないことも重要です。これにより、メモリリークが発生し、ブラウザで個別に適用する必要がある何千ものCSSルールが作成されるためです。私はこのようなことをします:

//Add the stylesheet once and store a cached jQuery object
var $style = $("<style type='text/css'>").appendTo('head'); 

function onResize() {
    var css = "\
        .someClass {\
            left:   "+leftVal+";\
            width:  "+widthVal+";\
            height: "+heightVal+";\
        }";

    $style.html(css);
}

このソリューションは、サイズ変更ごとにDOMを1回だけ変更することにより、スタイルを変更します。効果的なjsの縮小と圧縮のために、おそらくcssをきれいに印刷したくないでしょうが、わかりやすくするためにしました。

8
Brian Peacock

Jqueryを使用して、<head>にスタイルオーバーライドを追加します。

$('<style>.someClass {color: red;} input::-webkit-outer-spin-button: {display: none;}</style>')
.appendTo('head'); 
5
user2041268

特定のCSSクラスの値を変更するためのソリューションがあります。ただし、CSSをタグ内に保持している場合にのみ機能します。 exの外部ファイルからCSSへのリンクを保持するだけの場合。

<style src='script.js'></style>

このソリューションは機能しません。

たとえば、cssが次のようになっている場合:

<style id='style'>
.foo {
height:50px;
}
</style>

JS/jQueryを使用してタグの値を変更できます。

関数を作成しましたが、おそらく最良の関数ではありませんが、機能します。必要に応じて改善できます。

function replaceClassProp(cl,prop,val){

if(!cl || !prop || !val){console.error('Wrong function arguments');return false;}


// Select style tag value

var tag = '#style';

    var style = $(tag).text();
    var str = style;

// Find the class you want to change
    var n = str.indexOf('.'+cl);
    str = str.substr(n,str.length);
    n = str.indexOf('}');
    str = str.substr(0,n+1);

    var before = str;

// Find specific property

    n = str.indexOf(prop);
    str = str.substr(n,str.length);
    n = str.indexOf(';');
    str = str.substr(0,n+1);

// Replace the property with values you selected

    var after = before.replace(str,prop+':'+val+';');
    style=style.replace(before,after);

// Submit changes

    $(tag).text(style);

}

次に、タグ変数をスタイルタグIDと実行に変更します。

replaceClassProp('foo','height','50px');

これと$( '。foo')。css( 'height'、 '50px');の違いjQueryのcssメソッドで実行すると、.fooクラスを持つすべての要素がDOMで見えるstyle = 'height:50px'になります。あなたが私のやり方でそれをするなら、要素は手つかずであり、あなたが見る唯一のものはclass = 'foo'です

利点

  • クリアDOM
  • スタイル全体を置き換えることなく、必要なプロパティを変更できます

欠点

  • 内部CSSのみ
  • 編集する特定のスタイルタグを見つける必要があります

とにかく役立つことを願っています。

5
wopolow

CSSクラスのメンバーをその場で変更することはできません。ただし、新しい<style>タグを新しいcssクラス実装でページに追加し、クラスを切り替えます。例:

Sample.css

.someClass { border: 1px solid black; font-size: 20px; }

そのクラスを完全に変更したいので、新しいスタイル要素を作成します。

<style>
   .someClassReplacement { border: 1px solid white; font-size: 14px; }       
</style>

次に、jQueryを使用して簡単な置換を行います。

$('.someClass').removeClass('someClass').addClass('someClassReplacement');
3
Tejs
function changeStyle(findSelector, newRules) {
    // Change original css style declaration.   
    for ( s in document.styleSheets ) {
        var CssRulesStyle = document.styleSheets[s].cssRules;
        for ( x in CssRulesStyle ) {
            if ( CssRulesStyle[x].selectorText == findSelector) {
                for ( cssprop in newRules ) {
                    CssRulesStyle[x].style[cssprop] = newRules[cssprop];
                }

                return true;
            }
        }
    }

    return false;
}

changeStyle('#exact .myStyle .declaration', {'width':'200px', 'height':'400px', 'color':'#F00'});
2
Cycne

なぜ_.class_セレクターを使用して、そのクラスのすべてのオブジェクトのプロパティを変更しないのですか?

すなわち:

$('.myclass').css('color: red;');

2
JJ.

わかりました..同じ問題があり、それを解決しましたが、解決策は皆のためではないかもしれません。

削除するスタイルシートとルールのインデックスがわかっている場合は、document.styleSheets[1].deleteRule(0);などを試してください。

最初から、main.css(インデックス0)ファイルがありました。次に、新しいファイルjs_edit.css(インデックス1)を作成しました。このファイルには、ページがあったときに削除したいプロパティを持つルールが1つだけ含まれていましたロードが完了しました(他のJS関数も多数処理した後)。

これで、js_edit.cssmain.cssの後にロードされるため、 js_edit.cssにルールを挿入/削除するだけで、main.css

var x = document.styleSheets[1];
x.insertRule("p { font-size: 2rem; }", x.cssRules.length);

x.cssRules.lengthは、2番目(インデックス1)のスタイルシートにあるルールの数を返すため、最後に新しいルールが挿入されます。

多数のforループを使用して、変更するルール/プロパティを検索し、同じシート内でルール全体を書き換えることができると確信していますが、この方法の方がニーズに合わせて簡単です。

http://www.quirksmode.org/dom/w3c_css.html とても助けてくれました。

1
LGT

YUI 2および3にはモジュールスタイルシートがあり、それを実行できます(JavaScriptを使用してスタイルシートをその場で編集します)。 http://yuilibrary.com/yui/docs/stylesheet/ 。だから可能だと思う。これは$( "。some")。css({...})とは異なりますが、ユーザーが尋ねたように、スタイルシートからスタイル定義を実際に変更/追加/削除します。

1
cancerbero

この問題へのアプローチを本当に再考する必要があります。適切に作成されたセレクタを使用してクラスをアタッチすることは、このアプローチに対するよりエレガントなソリューションかもしれません。私の知る限り、外部CSSは変更できません。

1
Kevin Bowersox

このソリューションは、 Cycne を変更して、ES6構文を使用し、外部スタイルシートのループを早期に終了します。このソリューションは外部スタイルシートを変更しません

function changeStyle(findSelector, newDeclarations) {
    // Change original css style declaration.
    document.styleSheets.forEach((sheet) => {
      if (sheet.href) return;
      const cssRulesList = sheet.cssRules;
      cssRulesList.forEach((styleRule) => {
        if (styleRule.selectorText === findSelector) {
          Object.keys(newDeclarations).forEach((cssProp) => {
            styleRule.style[cssProp] = newDeclarations[cssProp];
          });
        }
      });
    });
  }

  const styleDeclarations = {
    'width': '200px',
    'height': '400px',
    'color': '#F00'
  };
  changeStyle('.paintBox', styleDeclarations);

また、HTMLのヘッドセクションに少なくとも1つのスタイルタグが必要です。たとえば、

<style> .paintBox {background-color: white;}</style>
0
Tovieye Ozi

これは議論に遅れる可能性がありますが、ここで話しているようなものが必要でしたが、本当に望んでいたことを何も見つけられず、簡単にそれをしました。私が必要としていたのは、表示スタイルを非表示にしたり非表示にしたりする方法で各要素を個別に明示的にアクセスすることなく、多数の要素を非表示および表示することでした。そこで、次のことを思いつきました。

<style>
  /* The bulk of the css rules should go here or in an external css file */
  /* None of these rules will be changed, but may be overridden */
  .aclass { display: inline-block; width: 50px; height: 30px; }
</style>
<style id="style">
  /* Only the rules to be changed should go in this style */
  .bclass { display: inline-block; }
</style>
<script>
  //
  // This is a helper function that returns the named style as an object.
  // This could also be done in other ways.
  // 
  function setStyle() { return document.getElementById( 'style' ); }
</script>
<div id="d1" class="aclass" style="background-color: green;">
  Hi
</div>
<!-- The element to be shown and hidden --> 
<div id="d2" class="aclass bclass" style="background-color: yellow;">
  there
</div>
<div id="d3" class="aclass" style="background-color: lightblue;">
  sailor
</div>
<hr />
<!-- These buttons demonstrate hiding and showing the d3 dive element -->
<button onclick="setStyle().innerHTML = '.bclass { display: none; }';">
  Hide
</button>&nbsp;&nbsp;
<button onclick="setStyle().innerHTML = '.bclass { display: inline-block; }';">
  Show
</button>

他の関連するスタイルシート(この場合はaclassルールを持つもの)の後にある埋め込みの名前付きスタイルシートでbclassルールを切り替えることにより、表示CSSルールを1か所で更新し、aclassルールをオーバーライドすることができます、独自の表示ルールもありました。

この手法の長所は、実際の作業を行う非常にシンプルで効果的な1行であり、JQueryやプラグインなどのライブラリーを必要とせず、変更が発生したすべての場所を更新する実際の作業が必要ないことです。 applyは、JavaScriptではなく、ブラウザーのcssコア機能によって実行されます。また、IE 9以降、Chrome、Safari、Opera、およびMicrosoft Edgeがエミュレートできる他のすべてのブラウザーで、デスクトップおよびタブレット/電話デバイスで動作します。

0
Howard Brown