web-dev-qa-db-ja.com

CSSが少ない:ネスト時に&演算子を悪用しますか?

Lessは、&演算子を使用して ネストの可能性 を拡張します。

.header        { color: black;
  .navigation  { font-size: 12px;
    &.class    { text-decoration: none }
  }
}

これにより、&が親セレクターに置き換えられ、実際のセレクターの権利が親セレクターに連結されます。通常の追加ではなく、.header .navigation.classとなり、.classになります。子孫であること:.header .navigation .class

これで、次のことも可能になります( ここも参照 ):

.header        { color: black;
  .navigation  { font-size: 12px;
    #some-id & .foo   { text-decoration: none }
  }
}

その結果、次のようになります。#some-id .header .navigation .fooここで試してください 。置換が行われ、親セレクターの前にセレクター(#some-id)があります。

私がこのようにコーディングすることは決してないという事実に加えて、これはおそらくすぐにあなたのスタイルシートを台無しにするので、私の質問:

この機能は文書化されていないので、それは機能ですか、それともバグである可能性が高いですか?
考えられる副作用はどれですか?

13
Christoph

私はまた、私たちがそれに遭遇して以来、この使用法についてさらに熟考してきました あなたが参照したその質問で 。これが&の「バグ」の使用であると明確に答えることはできませんが(BoltClockはバグではないバグではないという良い議論をしているようです)、それの価値について議論します(これは論理的な観点からはバグではないと主張します)。

しかし、論理的な議論の前に、私はそれが少なくとも意図されていないことを示しているように見える 別の短く簡単な引用 (「ネストされたルール」セクション)を見つけました: "&は現在のセレクターの親。」それでおしまい。 BoltClockが主張するように、追加するか追加するかは無関係のようです。意図されていたのは、その時点までの現在の「セレクターの親」のプレースホルダーであるということだけでした。言語の「ネスト」使用に関連して常に言及されているという事実は、それが存在するネストのポイントまでのネストの完全なセレクター文字列を指定するように設計されていることを意味します。その文字列がどのように使用されるか(事前または追加)は、コーダー次第です。

さて、あなたは「このようにコーディングすることは決してないだろう」と述べています(そして以前に述べました)が、それでも私はこれの非常に価値のある使用法のように見えるものを見ています。次の議論を考えてみてください。

イラストのHTML設定

説明のために、サイトの「外観」を変更するbody要素に3つの可能なクラス(「明るい」、「中」、「暗い」テーマ)の動的設定があると仮定します。 2つの列があり、テーマごとに各列で異なるスタイル(textLinkpicLinktextWithIconLink)するさまざまなタイプのリンクがあります。

<body class="light">
  <div class="leftCol">
     <a class="textLink"></a>
     <a class="picLink"></a>
     <a class="textWithIconLink"></a>
  </div>
  <div class="rightCol">
     <a class="textLink"></a>
     <a class="picLink"></a>
     <a class="textWithIconLink"></a>
  </div>
</body>

ここで尋ねる質問は、リンクを見るだけで、次の2つの方法のうちの...

  1. LESSのコードが少ない
  2. 最高の組織はLESSのコードです
  3. CSSで出力するコードが少なくなります
  4. 出力されたCSSを最適に整理します

「最高」はやや主観的かもしれません。その証拠を下から自分で比較検討させてください。

オプション#1典型的な入れ子

[〜#〜] less [〜#〜](約99行のコード)

/*Light Color Theme */
    .light {
      .leftCol {
        .textLink {
          color: fooL1;
          &:hover { color: barL1;}
        } 
        .picLink {
          background-image: url(/fooL1.jpg);
          &:hover { background-image: url(/barL1.jpg);}
        }
        .textWithIconLink {
          color: fooL2;
          background-image: url(/fooL2.jpg);
          &:hover { color: barL2; background-image: url(/barL2.jpg);}
        }   
      }
      .rightCol {
        .textLink {
          color: fooL3;
          &:hover { color: barL3;}
        } 
        .picLink {
          background-image: url(/fooL3.jpg);
          &:hover { background-image: url(/barL3.jpg);}
        }
        .textWithIconLink {
          color: fooL4;
          background-image: url(/fooL4.jpg);
          &:hover { color: barL4; background-image: url(/barL4.jpg);}
        }   
      }
    }
/*Medium Color Theme */
    .medium {
      .leftCol {
        .textLink {
          color: fooM1;
          &:hover { color: barM1;}
        } 
        .picLink {
          background-image: url(/fooM1.jpg);
          &:hover { background-image: url(/barM1.jpg);}
        }
        .textWithIconLink {
          color: fooM2;
          background-image: url(/fooM2.jpg);
          &:hover { color: barM2; background-image: url(/barM2.jpg);}
        }   
      }
      .rightCol {
        .textLink {
          color: fooM3;
          &:hover { color: barM3;}
        } 
        .picLink {
          background-image: url(/fooM3.jpg);
          &:hover { background-image: url(/barM3.jpg);}
        }
        .textWithIconLink {
          color: fooM4;
          background-image: url(/fooM4.jpg);
          &:hover { color: barM4; background-image: url(/barM4.jpg);}
        }   
      }
    }
/*Dark Color Theme */
    .dark {
      .leftCol {
        .textLink {
          color: fooD1;
          &:hover { color: barD1;}
        } 
        .picLink {
          background-image: url(/fooD1.jpg);
          &:hover { background-image: url(/barD1.jpg);}
        }
        .textWithIconLink {
          color: fooD2;
          background-image: url(/fooD2.jpg);
          &:hover { color: barD2; background-image: url(/barD2.jpg);}
        }   
      }
      .rightCol {
        .textLink {
          color: fooD3;
          &:hover { color: barD3;}
        } 
        .picLink {
          background-image: url(/fooD3.jpg);
          &:hover { background-image: url(/barD3.jpg);}
        }
        .textWithIconLink {
          color: fooD4;
          background-image: url(/fooD4.jpg);
          &:hover { color: barD4; background-image: url(/barD4.jpg);}
        }   
      }
    }

CSS出力(もちろんテーマ別に整理された約87行の出力)

 /*Light Color Theme */
.light .leftCol .textLink { color:fooL1; }
.light .leftCol .textLink:hover { color:barL1; }
.light .leftCol .picLink { background-image:url(/fooL1.jpg); }
.light .leftCol .picLink:hover { background-image:url(/barL1.jpg); }
.light .leftCol .textWithIconLink {
  color:fooL2;
  background-image:url(/fooL2.jpg);
}
.light .leftCol .textWithIconLink:hover {
  color:barL2;
  background-image:url(/barL2.jpg);
}
.light .rightCol .textLink { color:fooL3; }
.light .rightCol .textLink:hover { color:barL3; }
.light .rightCol .picLink { background-image:url(/fooL3.jpg); }
.light .rightCol .picLink:hover { background-image:url(/barL3.jpg); }
.light .rightCol .textWithIconLink {
  color:fooL4;
  background-image:url(/fooL4.jpg);
}
.light .rightCol .textWithIconLink:hover {
  color:barL4;
  background-image:url(/barL4.jpg);
}
/*Medium Color Theme */
.medium .leftCol .textLink { color:fooM1; }
.medium .leftCol .textLink:hover { color:barM1; }
.medium .leftCol .picLink { background-image:url(/fooM1.jpg); }
.medium .leftCol .picLink:hover { background-image:url(/barM1.jpg); }
.medium .leftCol .textWithIconLink {
  color:fooM2;
  background-image:url(/fooM2.jpg);
}
.medium .leftCol .textWithIconLink:hover {
  color:barM2;
  background-image:url(/barM2.jpg);
}
.medium .rightCol .textLink { color:fooM3; }
.medium .rightCol .textLink:hover { color:barM3; }
.medium .rightCol .picLink { background-image:url(/fooM3.jpg); }
.medium .rightCol .picLink:hover { background-image:url(/barM3.jpg); }
.medium .rightCol .textWithIconLink {
  color:fooM4;
  background-image:url(/fooM4.jpg);
}
.medium .rightCol .textWithIconLink:hover {
  color:barM4;
  background-image:url(/barM4.jpg);
}
/*Dark Color Theme */
.dark .leftCol .textLink { color:fooD1; }
.dark .leftCol .textLink:hover { color:barD1; }
.dark .leftCol .picLink { background-image:url(/fooD1.jpg); }
.dark .leftCol .picLink:hover { background-image:url(/barD1.jpg); }
.dark .leftCol .textWithIconLink {
  color:fooD2;
  background-image:url(/fooD2.jpg);
}
.dark .leftCol .textWithIconLink:hover {
  color:barD2;
  background-image:url(/barD2.jpg);
}
.dark .rightCol .textLink { color:fooD3; }
.dark .rightCol .textLink:hover { color:barD3; }
.dark .rightCol .picLink { background-image:url(/fooD3.jpg); }
.dark .rightCol .picLink:hover { background-image:url(/barD3.jpg); }
.dark .rightCol .textWithIconLink {
  color:fooD4;
  background-image:url(/fooD4.jpg);
}
.dark .rightCol .textWithIconLink:hover {
  color:barD4;
  background-image:url(/barD4.jpg);
}

オプション#2エンドターゲットのグループ化

これを「EndTargetGrouping」と名付けました。これは、親セレクターを追加するこの別の方法で&を使用する方法が実際にそうなっているためです。 1つは、実際にスタイル設定されている最終的なエンドターゲット要素に基づいてコーディングしています。

[〜#〜] less [〜#〜](約88行のコード)

/*Links */
/*Text  Links*/
.textLink {
  .light .leftCol &  {
      color: fooL1;
      &:hover { color: barL1;}
    }      
  .light .rightCol &  {
      color: fooL3;
      &:hover { color: barL3;}
    } 
  .medium .leftCol &  {
      color: fooM1;
      &:hover { color: barM1;}
    } 
  .medium .rightCol &  {
      color: fooM3;
      &:hover { color: barM3;}
    } 
  .dark .leftCol &  {
      color: fooD1;
      &:hover { color: barD1;}
    } 
  .dark .rightCol &  {
      color: fooD3;
      &:hover { color: barD3;}
    } 
}
/*Picture Links */
.picLink {
  .light .leftCol &  {
      background-image: url(/fooL1.jpg);
      &:hover { background-image: url(/barL1.jpg);}
    } 
  .light .rightCol &  {
      background-image: url(/fooL3.jpg);
      &:hover { background-image: url(/barL3.jpg);}
    } 
  .medium .leftCol &  {
      background-image: url(/fooM1.jpg);
      &:hover { background-image: url(/barM1.jpg);}
    } 
  .medium .rightCol &  {
      background-image: url(/fooM3.jpg);
      &:hover { background-image: url(/barM3.jpg);}
    } 
  .dark .leftCol &  {
      background-image: url(/fooD1.jpg);
      &:hover { background-image: url(/barD1.jpg);}
    } 
  .dark .rightCol &  {
      background-image: url(/fooD3.jpg);
      &:hover { background-image: url(/barD3.jpg);}
    } 
}
/*Text with Icon Links */
.textWithIconLink {
  .light .leftCol &  {
      color: fooL2;
      background-image: url(/fooL1.jpg);
      &:hover { color: barL2; background-image: url(/barL1.jpg);}
    } 
  .light .rightCol &  {
      color: fooL4;
      background-image: url(/fooL3.jpg);
      &:hover { color: barL4;  background-image: url(/barL3.jpg);}
    } 
  .medium .leftCol &  {
      color: fooM2;
      background-image: url(/fooM1.jpg);
      &:hover { color: barM2; background-image: url(/barM1.jpg);}
    } 
  .medium .rightCol &  {
     color: fooM4;
      background-image: url(/fooM3.jpg);
      &:hover { color: barM4; background-image: url(/barM3.jpg);}
    } 
  .dark .leftCol &  {
     color: fooD2;
      background-image: url(/fooD1.jpg);
      &:hover { color: barD2; background-image: url(/barD1.jpg);}
    } 
  .dark .rightCol &  {
      color: fooD4;
      background-image: url(/fooD3.jpg);
      &:hover { color: barD4; background-image: url(/barD3.jpg);}
    } 
}

[〜#〜] css [〜#〜]([1つの追加コメントによる]約88行の出力、エンドターゲット要素ごとに編成。ただし、クラス構造のため、テーマごとのサブ組織がまだ存在することに注意してください)

/*Links*/
/*Text  Links*/
.light .leftCol .textLink { color:fooL1; }
.light .leftCol .textLink:hover { color:barL1; }
.light .rightCol .textLink { color:fooL3; }
.light .rightCol .textLink:hover { color:barL3; }
.medium .leftCol .textLink { color:fooM1; }
.medium .leftCol .textLink:hover { color:barM1; }
.medium .rightCol .textLink { color:fooM3; }
.medium .rightCol .textLink:hover { color:barM3; }
.dark .leftCol .textLink { color:fooD1; }
.dark .leftCol .textLink:hover { color:barD1; }
.dark .rightCol .textLink { color:fooD3; }
.dark .rightCol .textLink:hover { color:barD3; }
/*Picture Links */
.light .leftCol .picLink { background-image:url(/fooL1.jpg); }
.light .leftCol .picLink:hover { background-image:url(/barL1.jpg); }
.light .rightCol .picLink { background-image:url(/fooL3.jpg); }
.light .rightCol .picLink:hover { background-image:url(/barL3.jpg); }
.medium .leftCol .picLink { background-image:url(/fooM1.jpg); }
.medium .leftCol .picLink:hover { background-image:url(/barM1.jpg); }
.medium .rightCol .picLink { background-image:url(/fooM3.jpg); }
.medium .rightCol .picLink:hover { background-image:url(/barM3.jpg); }
.dark .leftCol .picLink { background-image:url(/fooD1.jpg); }
.dark .leftCol .picLink:hover { background-image:url(/barD1.jpg); }
.dark .rightCol .picLink { background-image:url(/fooD3.jpg); }
.dark .rightCol .picLink:hover { background-image:url(/barD3.jpg); }
/*Text with Icon Links */
.light .leftCol .textWithIconLink {
  color:fooL2;
  background-image:url(/fooL1.jpg);
}
.light .leftCol .textWithIconLink:hover {
  color:barL2;
  background-image:url(/barL1.jpg);
}
.light .rightCol .textWithIconLink {
  color:fooL4;
  background-image:url(/fooL3.jpg);
}
.light .rightCol .textWithIconLink:hover {
  color:barL4;
  background-image:url(/barL3.jpg);
}
.medium .leftCol .textWithIconLink {
  color:fooM2;
  background-image:url(/fooM1.jpg);
}
.medium .leftCol .textWithIconLink:hover {
  color:barM2;
  background-image:url(/barM1.jpg);
}
.medium .rightCol .textWithIconLink {
  color:fooM4;
  background-image:url(/fooM3.jpg);
}
.medium .rightCol .textWithIconLink:hover {
  color:barM4;
  background-image:url(/barM3.jpg);
}
.dark .leftCol .textWithIconLink {
  color:fooD2;
  background-image:url(/fooD1.jpg);
}
.dark .leftCol .textWithIconLink:hover {
  color:barD2;
  background-image:url(/barD1.jpg);
}
.dark .rightCol .textWithIconLink {
  color:fooD4;
  background-image:url(/fooD3.jpg);
}
.dark .rightCol .textWithIconLink:hover {
  color:barD4;
  background-image:url(/barD3.jpg);
}

結論

その他の考慮事項:

まず、ほとんどのテーマの色(および場合によっては他のテーマの側面)は変数で設定されます。変数は、上記のオプション#2を使用しても、テーマごとにLESSコードの上部にグループ化できます。つまり、出力のテーマ構造があります。コードに散在するCSS自体は必ずしも悪いわけではありません。

次に、あるタイプの要素の「標準」コードは、テーマコードの上に定義されます。私の例ではこれは示されていませんが、すべての.textLink要素にtext-decoration: none;が設定されていると言います。これは、オプション#2で、セレクターコードを追加せずに一度発生し、以下のすべてのテーマの変更の上に表示されます。オプション#1の場合、すべてのテーマリンクに適用するために、新しいunested.textLinkセレクター(少なくとも他の1行のコード)を設定する必要があります。このクラスの「基本」コードは、テーマリンク情報の残りのコードがどこにあるかとは無関係です。

第三に、開発者として、picLinks(ページ上の特定のタイプの要素)に問題がある場合、オプション#2を使用すると、問題のある要素のコードをはるかに簡単に調べることができます。すべてのテーマのすべてのコードが1か所にあるためです。

明らかに、最終的なLESSとCSSをどのように整理するかが、これの価値をどのように見るかについての主要な要因になります。ここでの私のポイントは、親レベルのセレクターを&参照に追加するこの方法で&を使用する非常に有用で論理的な理由があることを単に示すことです。

8
ScottS

&コンビネータの乱用ではありません。ネストされたセレクターにどこでも配置でき、その上にあるもの(いわゆる親セレクター)に置き換えられます。

[&コンビネータは]ネストされたセレクタを子孫として機能するのではなく、その親セレクタに連結する場合に使用されます。

「連結」と表示されていることに注意してください。ネストされたセレクターに親セレクターを追加または追加することしかできないとは言いません。連結は特定の方向でのみ機能しません。

さらに、「子孫」という言葉は、ネストされたセレクターがデフォルトで子孫コンビネーターによってリンクされているかのように扱われるという性質と関係があります。これは、本質的に&の使用を子孫のみに制限するものではなく、ネストされたセレクターを追加するだけの方法で親セレクターが親または祖先要素を表す必要があることを意味するものでもありません。先頭に追加したり、途中に挿入したりすることはありません。

5
BoltClock