用意图明确的CSS选择器直击元素

       原文http://csswizardry.com/2012/07/shoot-to-kill-css-selector-intent/

       有一类CSS是我每次看到都不敢恭维的,那就是意图不明确的选择器。这样意图不明确的选择器意味着你要去地毯式轰炸出你想选择的那个元素。对比.header ul{}与.main-nav{},.widget h2{}与.widget-title,article > p:first-child{}与.intro{}。显然选择器的意图不够明确。

       如今,一个选择器的意图是什么确实非常值得注意,如果再搭配一个显而易见的名字就更能让人理解了!

让我们仔细研究一下.header ul{}这个例子。假设这个ul确实是我们网站的主导航。它在header里面,正如你所料,现在只有一个ul在那里,.header ul{}确实运作良好。事实真的是这样吗?答案是不一定的。我肯定这样的选择器确实达到你想要的效果,但这样做并不好,对于未来这没有良好的拓展性,而且意图也不够明确。一旦我们再往header里添加另外一个ul,它就会延续main nav的样式,但这个样子并不是我们想要的。这意味着我们要选择去重构许多代码或者去解除.header对随后添加的ul产生的影响。

       你的选择器意图必须匹配你命名这样东西的原因。问问你自己:“我这样选择是因为ul在.header里面还是因为它是网站里的主导航?”这个问题的答案将主导你的选择。

       这里的关键是核心选择器:

       怎样的选择器是核心选择器呢?要知道哪个才是核心选择器就必须清楚浏览器是从右到左解析CSS的。这意味着核心选择器就在大括号“{”的前面,例如:

.headerul      { /* ‘ul’ 是核心选择器*/ }

.ulli a        { /* ‘a’ 是核心选择器*/ }

p:last-child    { /* ‘:last-child’ 是核心选择器*/ }

       我在编写高效的CSS选择器中也讨论过这个问题,核心选择器的正确使用对提高CSS效率上起着至关重要的作用。所以去要关注选择器的深度是不是明确对应你的选择意图。比如

       . html > body > section.content >article span{},这样的选择器是不但可笑而且令人费解。核心选择器(span)太深,非常难找。虽然找到span有很多方式,但选择哪种方式是很重要的。

         一般来说,你应该尽量避免核心选择器是基本元素,如ul、span等,还有不要作为一个基础对象,如.nav、.media。因为即使.media在你现在的上下文中是唯一对象,但事情不一定总是这样。

         让我们继续研究.header ul{}这个例子。假设我们将ul抽象成nav:

<div class=header>

           <ul class=nav>

          [links]

           </ul>

</div>

        我们可以通过几种方式去选择它:

.header ul{

   [main nav styles]

}


         这是一个不好的选择,因为我们有可能会增加其他的ul到header里,这样的话新增的ul样式就只能跟main nav一样了。但幸运的是这样的情况很容易避免。

         第二种方式我们使用:

.header .nav{

[main nav styles]

}

       这种方式稍微比第一种要好,但仅仅是比第一种好一点。我们现在可以毫无顾忌地添加其他的ul进来,但我们不能添加其他含.nav的元素进来,这意味着如果要增加子导航或者面包屑导航将会是一场噩梦。

       最后,最佳实践应该是在ul中增加多一个类,为.main-nav:

<div class=header>

   <ul class="nav  main-nav">

        [links]

   </ul>

</div>

.main-nav{

   [main nav styles]

}

       这才是一个明确的选择器意图。我们现在选择这个元素是有明确指向与原因的,而不是间接选择的。现在我们就可以添加更多的ul和nav进来.header里,而且main nava的样式作用域不会影响到其他地方。这样一来,我们就不需要为了找某个元素而进行地毯式轰炸了。

       保持你的核心选择器是明确并且具体的,即使它比其他类更长。一个模糊的选择是很危险的,一个通用选择器就必须是具有通用的命名(比如上面的nav),当你想要特殊化某一样东西的时候,直接在通用选择器的基础上再加一个类上去(比如上面的main-nav)。具体的意图需要一个具体的选择器。

       一个真实的例子:

       这是我曾经在一个项目中搞砸的一个例子。我写了个选择器#content table{}。(我竟然使用ID选择器!!)这里有三个原因说明这是一个糟糕的选择器。第一,使用ID是一大禁忌。第二,它具有太高的权重,并且意图不明确。第三,其实我只是想表示这个table是在#content里面而已。全是我的错。

一开始那几个星期还没出什么问题,但突然,我们需要增加一些table进去#content那里但他们的样式要跟一开始那个不一样。哎,我之前写的选择器影响太深远,以至于我必须得想办法解除这样的束缚。我将每个table都放在#content div里,除非有更好的代替方案:

#content table{

   [foo styles]

}

#content .bar{

   [undoing foo styles]

   [bar styles]

}

我不得不这样做:

.foo{

   [foo styles]

}

.bar{

   [bar styles]

}


这就减少了许多头痛的问题。通过预判和深思熟虑选择器的意图,我将会更轻松。

       例外:

       当然例外的事情也是有的。在你想选择某个类型的时候,.main-nav > li这样的选择器是完全正确的。同样地下面对于想选择每个a标签来说也是正确的:

html{

   color:#333;

   background-color:#fff;

}

 

/* Inverted colour scheme forpromotional items. */

.promo{

   color:#fff;

   background-color:#333;

}

   .promo a{

        color:#fff;

        text-decoration:underline;

   }


这种情况下,即使是这样的地毯式轰炸方式也是相当明智的。

       最后说说:

       一般来说,直击你想要的元素是要比地毯式轰炸要好的。要反复推敲选择器针对让你的目标元素是否具体而明确。

       反复思考你所选的是什么并且作出一个更加具体与明智的选择,提炼你的选择意图。

       你的意思是:

       .header em{}

       还是你真正的意思是:

       .tagline{}

       你的意思是:

       .footer p{}

       还是你真正的意思是:

       .copyright{}

       你觉得这是一个明智的选择:

       .sidebar form{}

       还是有更加安全地选择:

       .search-form{}

       认真思考你的CSS选择意图,问问自己意图是否足够明确?你选择器使用的理由是否足够充分?还是只是你一时高兴就这样子做?我们要做CSS的狙击手,而不是CSS的地毯式轰炸兵,我们需要一击即中。

       选择使用.main-nav会比.header ul少更多特殊权重的束缚并且提高选择效率,从而达到双赢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值