13

CSSを使用して多層背景の1つの層を変更する方法を知っている人はいますか?

私は探し回っていますが、現在の、または提案されている将来の仕様についての言及を見つけることができません。私の考えではおそらくないだろうと言っていますが、ネットは非常に広大で、どこかで誰かがこれらの線に沿った議論への情報やリンクを持っていると確信しています。

次の例では、さまざまな要素に適用した場合の優先順位に関して明らかに問題があります。

.building-texture {
  background: transparent, url(image/building-side.png);
}

.shade-dark {
  background: url(image/shade-dark.png), unchanged;
}

.shade-mid {
  background: url(image/shade-mid.png), unchanged;
}

.shade-light {
  background: url(image/shade-light.png), unchanged;
}
<div class="building-texture shade-dark"></div>

明らかに、上記にはいくつかの回避策がありますが、特に多くの異なる「レイヤー状態」といくつかの異なる「テクスチャ」について話し始める場合、理想的なものはありません。

初期ソリューション

結合されたクラス

これはフォールバックの中で最も最適ですが、ベンダープレフィックスを考慮に入れ始めたり、3つ以上のレイヤーを処理したりすると、ばかげています。

.building-texture-shade-dark {
  background: url(image/shade-dark.png), url(image/building-side.png);
}

.building-texture-shade-mid {
  background: url(image/shade-mid.png), url(image/building-side.png);
}

.building-texture-shade-light {
  background: url(image/shade-light.png), url(image/building-side.png);
}

別々の要素

いくつかのテストをローカルで実行すると、マルチレイヤーの背景がサブ要素を使用するよりも高速に実行されることがわかりました。実際、最近のほとんどのブラウザーでは、単純な子(背景が適用されていない)を導入しただけでも、レンダリングがかなり遅くなりました。

<div class="building-texture">
  <div class="shade-dark"></div>
</div>

JavaScriptの生成

最初のオプション(組み合わせたクラス)を手動で入力する手間を省くために、JavaScriptを使用してスタイルシートを生成することができます。しかし、あなたはまだ長いクラス名の厄介さを持っています。さらに、結合されたクラスの1つの適用された効果を変更する場合(たとえば、シェーディングを削除する場合)、命名規則に基づいてその方法を理解する機能をスクリプト化する必要があります。

JavaScriptによるスタイルプロパティ

.styleもう1つのオプションは、各要素を介して背景全体を動的に書き換えることです。私はこれをテストしていませんが、ブラウザがプリセットクラスを処理するときに(つまり、要素のレンダリングを分類ごとにグループ化することによって)かなりの数の最適化を実行できると確信しているため、これはかなり非効率的であると頭から言われています。私は間違っているかもしれませんが。

なぜ...

私はCSS3D変換(遠近法を有効にしたもの)と、そのような構造をシンプルかつ高速にテクスチャリング/ライト化するための最良の方法(サンプルコード)で遊んでいます:

http://pebbl.co.uk/wote/

サンプル画像
(出典:pebbl.co.uk

満足のいくCSSソリューションの作成に失敗した後、私は現在、必要なすべてのテクスチャを、さまざまなシェーディング状態とともに事前に構築し、キャッシュされたデータURIを生成するCanvasベースのソリューションに向かっています。単層の背景として添付されます。私のテストでは、これが最適であることが示されています。ただし、キャンバスにはより多くのコードが含まれるため、できるだけ多くのネイティブブラウザベースのソリューションを使用したいと思います。また、今日のブラウザは急速に改善されているため、ホイール、エンジン、または道路網。

私が行っているのはCSSの「適切な」使用ではないと思われるかもしれませんが、私の意見では、各背景項目はそれ自体の単位です。私にとっては、それぞれを変更するための特定の方法があるはずです。ユニットを個別に...将来的には離れていても。

これらの線に沿った議論へのリンクを含む回答に興味があります。

4

2 に答える 2

4

残念ながら、通常の CSS でそれを行う方法はありません。プロパティの一部ではなく、プロパティ全体のみを変更できます。background-imageこれが、最初にのような個別のプロパティがある理由background-colorです。しかし、それ以上にきめ細かいものはありません。

ScottS が示唆したように、疑似要素を使用することもできますが、複数の個別の div 要素と同じ問題が発生する可能性があります。

主な目標がコードを何度も入力することを避けることである場合、良い解決策はSASSのような CSS プリプロセッサを使用することです。SCSS は次のようになります。

$img-side:  url("image/building-side.png");
$img-dark:  url("image/shade-dark.png");
$img-mid:   url("image/shade-mid.png");
$img-light: url("image/shade-light.png");

.building-texture {
  background: transparent, $img-side;
}    
.shade-dark {
  background: $img-dark, $img-side;
}    
.shade-mid {
  background: $img-mid, $img-side;
}    
.shade-light {
  background: $img-light, $img-side;
}

より大きな CSS (完全な URL 定義を含む) にコンパイルされますが、開発時間を大幅に節約できます。SASS は、ミックスインを使用してベンダー プレフィックスを生成するのにも役立ちます (それを SASS に追加する Compass もあります)。

実際、将来的に使用できるCSS 変数の仕様が予定されていますが、まだサポートしているブラウザーはないと思います。

于 2013-01-21T15:33:00.430 に答える
3

疑似要素で抽象化する

単一の背景を「交換」する方法はまだ知りません。1 つの回避策は「要素を分離する」手法に基づいていますが、内部要素は代わりに疑似要素です。レンダリング速度についてはわかりません。また、擬似要素に適用できないfilterため、IE8 では機能しないという欠点もあります。ただし、CSS3 パースペクティブなどと組み合わせてアイデアを使用しているため、IE8 の警告は問題になりません。

これにより、シェーディングからのテクスチャの抽象化が実現されます。疑似要素を介して別のレイヤーを追加する:afterこともできます。必要に応じて、3 つのそれぞれに複数の背景を使用することもできます。

これがフィドルです。

サンプルコード:

HTML

<div class="texture"></div>
<div class="texture light"></div>
<div class="texture medium"></div>
<div class="texture dark"></div>

CSS(コア)

.texture {
    position: relative;
    background: url(http://www.dummyimage.com/12x16/ff0000/ffffff.png&text=X++) top left repeat;
}

.light:before,
.medium:before,
.dark:before {
    content: '';
    position: absolute;
    top:0;
    right: 0;
    bottom:0;
    left: 0;
}
.light:before {
    background: -moz-linear-gradient(left,  rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.1) 100%);
    background: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(0,0,0,0.3)), color-stop(100%,rgba(0,0,0,0.1)));
    background: -webkit-linear-gradient(left,  rgba(0,0,0,0.3) 0%,rgba(0,0,0,0.1) 100%);
    background: -o-linear-gradient(left,  rgba(0,0,0,0.3) 0%,rgba(0,0,0,0.1) 100%);
    background: -ms-linear-gradient(left,  rgba(0,0,0,0.3) 0%,rgba(0,0,0,0.1) 100%);
    background: linear-gradient(to right,  rgba(0,0,0,0.3) 0%,rgba(0,0,0,0.1) 100%);
}
.medium:before {
    background: -moz-linear-gradient(left,  rgba(0,0,0,0.6) 0%, rgba(0,0,0,0.2) 100%);
    background: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(0,0,0,0.6)), color-stop(100%,rgba(0,0,0,0.2)));
    background: -webkit-linear-gradient(left,  rgba(0,0,0,0.6) 0%,rgba(0,0,0,0.2) 100%);
    background: -o-linear-gradient(left,  rgba(0,0,0,0.6) 0%,rgba(0,0,0,0.2) 100%);
    background: -ms-linear-gradient(left,  rgba(0,0,0,0.6) 0%,rgba(0,0,0,0.2) 100%);
    background: linear-gradient(to right,  rgba(0,0,0,0.6) 0%,rgba(0,0,0,0.2) 100%);
}
.dark:before {
    background: -moz-linear-gradient(left,  rgba(0,0,0,0.8) 0%, rgba(0,0,0,0.3) 100%);
    background: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(0,0,0,0.8)), color-stop(100%,rgba(0,0,0,0.3)));
    background: -webkit-linear-gradient(left,  rgba(0,0,0,0.8) 0%,rgba(0,0,0,0.3) 100%);
    background: -o-linear-gradient(left,  rgba(0,0,0,0.8) 0%,rgba(0,0,0,0.3) 100%);
    background: -ms-linear-gradient(left,  rgba(0,0,0,0.8) 0%,rgba(0,0,0,0.3) 100%);
    background: linear-gradient(to right,  rgba(0,0,0,0.8) 0%,rgba(0,0,0,0.3) 100%);
}
于 2013-01-21T15:13:41.507 に答える