您所在的位置:小祥子 » 编程 » CSS » 正文

选择器

时间:2015-05-30 编辑:lazycat-cz 来源:本站整理

  CSS选择器有很多种,每次看别人写的跟背书一样,没办法,种类就那么多,只能一一罗列,还能玩出什么花样?所以重要的就是清楚为什么要这样用,好处在哪里了。

  1. 标签选择器

  在CSS中,有的标签本身已经具有一些样式,比如h1,通常会作为标题,它的字体比一般的大,默认为粗体,而且是块级标签,四周有margin值。标签选择器,本质上来说,就是给一个标签重新定义样式。还是h1,因为用它作标题有利于搜索引擎,所以经常用,但它自带的样式有时(恐怕是多时)与网页布局显得很不合理,所以我们完全可以重写它的样式,改变字体大小,去掉margin等,以达到整体控制的效果。只要重定义了它的样式,直接用h1将显示运用了新样式后的文本内容,这样更和谐了。

    h1{font-size:1em;}

  2. 类选择器

  既然是类,更多的是对一个或几个元素产生影响,为了减少工作量和精确控制,对相同的类型的一些元素给一个相同的class名,是很不错的选择,重点是可以在一个class中添加多个类名,更加省时。如这里三个选择器各添加不同的样式,都会加载到这段文本上。当然CSS样式是就近原则,后面的覆盖前面的,优先级高的覆盖优先级低的,所以假如mr也设置了font-size,它将覆盖掉ft选择器中的font-size。

    .ft{font-size:24px;}    
    .mr{margin:10px;}
    .fl{float:left;}
    <p class="ft mr fl ">Hello World</p>

   专业的前端通常会同时使用几个类,一个fl,表示飘浮到页面左边,单独写一个样式,需要时就加上,因此它更像一个工具,拆分成多个类名,扩展性更强。注意类名中可以出现 - 或 _ ,这是允许的。

  3. ID选择器

  ID给人一种唯一标识的感觉,所以它经常是刻划网页上一个特殊的部位,更多的是表示某一部分内容,比如横幅(banner)、边栏(sidebar)、主要内容(main)等,如划分一个大块时经常这样像下面这样,当然如果你说我就喜欢用ID选择器,我把所有的标签都加ID,唯一结果就是肯定不会有人过去咬你-_-#

    #news{
        margin-left:10%;
        font-family:"Times New Roman"
     }
     <div id="news">
         ........
     </div> 

  关于ID有个重点就是它具有高优先级,比如下面

    #link{ color:red; }
    .link{ color:blue; }
    <a id="link" class="link" href="#">To Somewhere</a>

  它是红色还是蓝色?演示就知道是红色,因为ID选择器具有更高的优先级,浏览器会根据ID和class(或者组合)计算出一个权重值,谁的大用谁的样式(理论上是这样,但用Chrome试过好像也不一定),权重值的计算如果深究也有点麻烦,特别是不只一个ID、class、标签纠缠在一起时。如何计算权值网上也有文章分析,当然我们何必要为难自己呢,至少我自己(向前端学的)有时做简单的页面,只用类选择器,只在有时用JS时为了快速取到元素才加id,基本不用ID选择器添加样式,避免麻烦。 

  4. 群选择器

  如果看过专业前端的css代码,肯定在最开头有类似这样的:

    body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li{ margin: 0; padding: 0; }

  一开始偶不明白为何弄这样一大堆标签,以为是设计时对样式从整体到局部的把握,所以先给所有的标签元素一两个基本的、整体的样式,像这里margin、padding就是让它们所有的标签都归为0。后来发现,这么说也不能说全错,但更重要的是,很多浏览器在处理一些自带样式的标签时(如h1~hn),虽然左右是有空白的,但有的使用margin,有的使用padding,不统一可能带来样式上的错乱,为了让样式在更多浏览器上显示一致,所以这里干脆去掉它们的margin、padding,当要使用某个标签时,再给单独添加margin、padding。这里的一大堆标签,以逗号分隔的选择器,称为群选择器,表示把它们都设置成一个后面括号中样式。群选择器不限于标签,class、id也可以这样干:.link, .news, #banner{...}。群选择器在设置一大堆具有相同样式的标签、类、ID时很方便。关于上面那个一大堆把margin、padding置为0的、提高显示一致性设计,有个名字叫CSS Reset,样式重置,这是偶这种小白平常用不到的。

  5. 通用选择器

  群选择器一次设置多个很爽,堆在一起用逗号分隔即可,还有更爽的,就是通用选择器,它就是一个 * ,代表所有选择器(通用嘛),比如下面

    h1, h2, p{font-weight:bold;}
    * {font-weight:bold;}

  第二个通用选择器等同于设置了第一个群选择器的内容,当然能比它代表更多的东西。

  6. 派生选择器

  这应该是专业前端最最常用的类型了,也称后代选择器。我们知道html标签是嵌套的,外面的是父元素,里面的是子元素,当然父子关系是相对的,这叫做html的族谱,当然它也有根节点,兄弟节点等,这根二叉树完全一样,所以也有相应的父标签、祖先标签、兄弟标签等等。比如像这样的

    <div id="nav">
        <ul class="nav">
             <li></li>
             <li></li>
        </ul>
    </div>    

  ul是div的子标签,li是ul的子标签,id选择器在类选择器nav的标签的父标签里边,所以定位到<li>标签的选择器可以这样写:

    #nav .nav li{...}

  需要注意的地方就是中间有空格,空格表示子标签,或者是位于子标签中的选择器,即一种父子关系,子孙关系也可,爷孙关系当然也行,总之就是:派生关系。对于派生选择器,如果不隔一个空格就是完全另一种情况,比如这里如果写 div#nav ul{...}(div紧挨着#nav)表示的就是:<div id="nav"><ul>,给id为nav的div标签,它的子标签为ul设置样式,是一个限制的并且关系,如果是div #nav ul{...},就是div标签的id为nav的子标签,它的子标签为 li 时的情况。空格很重要!

  看看专业前端的代码,派生选择器会占到百分之八九十,而且风格比较统一,派生时尽可能用class,当然最后会有一些标签选择器,但风格真的很好,不是一会儿类选择器,又夹个ID选择器,再来个标签选择器,最后再搞个ID选择器,这样看起来十分紊乱,一点也不丝滑,专业人士写的就是有种和谐的美感。

   

  除了一会ID选择器一会儿类选择器不好看之外,有个很大的原因是:很有可能你设计的这个样式根本没有运用到指定的地方,虽然很希望是它用到你指定的地方。比如

    <div id="id_wrap" class="cl_wrap">
        <p id="id_seg" class="cl_seg">
            Hello World
        </p>
    </div>
    1  div p {...}
    2  #id_wrap #id_seg{...}
    3  .cl_wrap .cl_seg{...}
    4  .cl_wrap #id_seg{...}
    5  div #id_seg{...}
    6  div .cl_seg{...}
    6  .cl_wrap p{...}
    7  #id_wrap p{...}
8 div.cl_wrap p{...}
9 #id_wrap p.cl_seg{...} ... ...

  这9个样式都可以运用到Hello World上(单独写的话),继续组合下去,还有,如果把这些都写出来,最后哪一个会真正加载到文本内容上呢?这里就有一个权重值的问题,前面说过,就权值来说,ID选择器最大(在选择器中),看过一本书上说:标签选择器1分,类选择器10分,ID选择器100分,内建样式1000分。内建样式即是类似<div style="width:100px;">这样的,直接在标签上给style。然后将用到的选择器权值按类型不同相加(如div p 是2分,.cl_wrap #id_seg 是110分,div.cl_wrap p是12分),结果最大的最终运用到指定内容上,但是貌似也不准确...不知道我测的对不对。计算完了,还要结合就近原则,看看哪些属性被覆盖了,哪些是继承了父元素的(如font-size,如果父元素是16px,子元素的font-size如果写的是100%就是16px,如果父元素是24px,子元素设置150%就是36px),还要看看哪些是永远保留的样式(下面,就近原则也覆盖不了)等等,这么搞下去怕迟早要疯掉...

    /* !important表示这个属性将永远不会被覆盖 */
    .seg{ font-style:bold !import; }

   有文章对这个权值进行计算分析,偶就还是懒惰的逃避了...所以专业前端的用类选择器是没有错的,只要定位得够精确,遵循统一规范,不临时变道加个ID选择器之类的,基本不会出错。

  使用派生选择器的另一大优点就是节省工作量。一个划分好布局的网页上,一块块的div中风格总是尽量的保持统一,从父元素到子元素总有很多属性相同,而css的样式是可以继承的,比如父元素的字体时16px,如果子元素不设置font-size,子元素中的字体大小将也是16px,当然也不是所有的样式都可以继承(有专门列表),如line-height行间距,这是合理的,如果父元素16px的字体大小行间距是16px,如果现在子元素的字体为54px额行间距仍是16px,就可能使得子元素中的字体行之间很紧凑甚至发生重叠,因为字体大小增大了很多行间距没变,试试可以看到效果。正式由于样式的可继承性,导致派生选择器更好用了。

  7. 子选择器

  根据html中标签结构的父子之分而来,形式 A > B,尖括号表示父子关系,注意不一定表示B一定是A的直接子标签,可能是可能是孙子、曾孙、曾曾孙,编程中的父子结构相信你知道,说a是b的子节点,不是非要a就是b的直系后代,所以div > p{...}表示div标签中的所有(直接或间接的)子标签,div p也是这样。

  8. 同胞选择器

  对共一个父元素的标签而言,它们是兄弟(或者姊妹?)关系,在css中叫同胞,而在位置上紧挨着的是临近同胞,所以css针对这种结构有一种称为临近同胞选择器,如

    <div>
         <h1>head</h1>
         <p>Hello</p>
    </div>
   /******/
   h1 + p {...}

  h1和p是临近同胞(兄弟),h1 + p 则表示选则了紧挨在h1后面,与h1共父元素的标签p。

  9. 通用同胞选择器

    它是对同胞选择器的延伸,h1 + p只能对具有兄弟关系,且紧挨在h1后面的p元素起作用,那么 h1 ~ p就表示选中了具有兄弟关系的,h1后面的所有p标签。

    <div>
         <h1>Hello</h1>
         <strong>Hello</strong>
         <p>我被选中</p>
         <em>Hello</em>
         <p>我被选中</p>
    </div>

  10. 伪类

  伪类选择器有很多,有时我们匹配的不是单个元素,而是某种状态,某种特殊的结构(简单的兄弟选择器表达不出来),或者某个动作的瞬间,比如鼠标滑过链接时,无序列表中的奇数列,这种情况的选择器,css给了个名字:伪类。

      捕捉动作的,最常见的是链接,,a:link,a:visited,a:hover,a:active,分别表示未访问前,已访问过,滑过时,鼠标点击的一瞬间,a与:之间没有空格。这四个伪类的设置是有顺序的,就是这里所列出的,如果hover放到了link的前面(如下),鼠标滑过时会发现链接还是绿色的,因为他们的权重都相同,按照就近原则,后边的样式覆盖前边的(样式冲突),鼠标滑过应用的将是a:link的样式,所以要按顺序来,某书介绍了一种记法 LoVe, HAte。 在有些选择器上,hover不仅是链接的专利,比如p:hover,滑过段落时改变样式,当然只是一些浏览器、一些高版本的可以,得看具体情况。伪类的书写不一定前面就是标签,<a id="lnk">可以是#lnk:hover,css很多地方均是同理,不要理解的很死板。

    a:hover{color:red;}
    a:link{color:green;}

  :focus捕捉当获得焦点时的响应,如文本框变背景色。

  匹配目标,:target,如果一个url中带有#aaa,恰好html中有带有id为aaa的标签,则匹配的是它,它用在页面内的锚点,如下,点击跳到页面内跳到锚点处可以发现它的样式已经改了(不知道br够不够)

    div :target{background-color:red;}

    <p><a href="#goto">跳到页面内goto</a></p>
    <br/><br/><br/><br/><br/><br/><br/>
    <br/><br/><br/><br/><br/><br/><br/>
    <br/><br/><br/><br/><br/><br/><br/>
    <br/><br/><br/><br/><br/><br/><br/>
    <br/><br/><br/><br/><br/><br/><br/>
    <br/><br/><br/><br/><br/><br/><br/>
    <div>
        <p name="goto" id="goto">锚点goto</p>
    </div>

    捕捉根节点,:root,html页面就是html节点了。

  捕捉特殊子节点的,:first-child、:last-child、:first-of-type、:last-of-type等。字面义可看出是第一个子节点,或第一个子类型。值得注意的是p:first-child与p :first-child完全不同(后者两个之间有空格),前一个很容易以为,它是指p标签的第一个子节点,但实际上第二个才是这样的正确写法,而p:first-child指的是,p作为其他标签的第一个子标签,它匹配的应该是这样的

    <div>
        <p>匹配了这里</p>
        <span><p>也匹配了这里</p></span>
    </div>

  同理,p:first-of-type,指的是,作为其他元素的子元素,匹配的第一个出现的标签为p的元素,即首先,p是其他元素的子元素,第二,匹配的是子元素中第一个出现的p标签,前面有其他的类型子标签不要紧,只要不是p就行,即使它后边还有相同的p兄弟标签,因为不是第一个出现的,也不符合。

  这种有点麻烦的情况,就要问问,它是它的子元素吗?它是它下面第一个出现的x标签吗?符合就是对的,如

    <div>    
    <h1>标题</h1>
    <span>
           <p>我是span的子标签中第一个出现的p</p>
    </span>
    <p>我是div的子标签中第一个出现的p</p>
    </div>    

   而 p :first-of-type(有空格),是指p标签下的第一个子元素,因为没指定类型,所以只要是p标签下边的第一个子类型,就会匹配到,等同于p :first-child,如果是p span:first-of-type,就是指p标签下,第一个类型为span的子标签。

  匹配只有一个子元素的,:only-child,如p:only-child(没有空格),匹配以p作为子元素,且它的父元素只有它这一个子元素的情况。

  按一定规律的匹配子元素,以:nth-child为例,从字面意义可知是第n个子元素,形式非常灵活。比如现在有一个无序列表栏目,以它为例

    <ul class="nav">
         <li>A</li>
         <li>B</li>
         <li>C</li>
         <li>D</li>
         <li>E</li>
    </ul>

       第一种,直接给一个数值,.nav li:nth-child(2)表示:li是类名为nav的子标签,且匹配第2个这样的标签,这里li都是ul的子标签,匹配其中第二个就是B了。

       第二种,匹配奇偶项,如.nav li:nth-child(odd),表示匹配列表中奇数项列表,括号里的odd是个参数,表示寻找奇数列(单词也表此意),A是第1列(从1开始计数),C是第3列,包括第5列E都符合,同理有偶数匹配,.nav li:nth-child(even)。

   第三种,使用表达式,比如.nav li:nth-child(2n+3),css不仅自己知道第一条列表的n值是1,第二条是2,而且在计算2n+3是几的时候,从0开始取自然数,所以2n+3就是对应着第3条、第5条、第7条...这种带n的表达式更加灵活。

  ok,类似于:nth-child,还有:nth-of-type(n)、:nth-last-child(n)(倒数第几个)、:nth-last-of-type(n)(倒数第几个类型)等等就很好理解了。

  伪类中还有匹配某种状态的,如下,比如哪些文本框不可用(设置了disable属性),单选框是否被选中等

    .txt:checked
    .txt:enabled
    .txt:disabled

  11.伪元素

  匹配某个元素的特殊位置,起了个名字叫伪元素。如下,如字面义,:before匹配p标签文本内容的开始地方,:after匹配其结束的地方,content的内容规定在文本开始加上Start,结束时加上End~。first-letter匹配首字母,first-line匹配首行。

    p:before{content:'Start";}
    p:after{content:"End~"}
p:first-letter{color:red;}
p:first-line{color:green;}

  12.属性元素

  属性元素非常常用,特别在js中,怎么能少的了。属性选择器当然跟标签带有的属性相关,就是根据这些标签带有的某些属性来做的匹配

  第一种,如A[attr],匹配带有attr属性的A标签,如下,匹配带有target属性的a标签,因此捕捉到第2个<a>

     a[target]{color:green;}
     <a href="http://www.css.org/">to css</a>
     <a href="www.example.com" target="_blank">to example</a>

  第二种,A[attr=value],匹配带有attr属性且属性值为value的元素,那么上例的匹配可以这样写,a[target=_blank]{...},将_blank加引号也可。

  第三种,A[attr~=letter],匹配带有attr标签,且标签的属性值中带有letter单词的A元素,如

    p[class~=news]{color:red;}
    <p class="wrap news"></p>

  第四种,A[attr|=value],匹配带有attr属性,且属性值以value开头或者value-开头,最适合的就是规定元素语言属性的时候,在html页面中可告知浏览器,这里用什么语言,有个lang属性,如下,匹配的是第一个。

    p[lang|=en]{color:red;}
    <p lang="en-us">I am CSS</p>
    <p lang="zh-cn">层叠样式表</p>

  第五种,使用通配符*,A[attr*=value],只要A标签带有attr属性,且属性值中包含字符串value即匹配

  最后两种,检测属性值的开头和结尾,分别是A[attr^=value]:匹配带attr属性,且属性值以value开头的A元素,如检查链接a[href^=http],而A[attr$=value]则匹配以value结尾的attr属性值的A,如某些下载链接检测a[href$='.zip']。

   最后属性选择器完全可以混用,比如在某个表单中,用jQuery选中元素对象时

    <div>
    <input type="radio" name="type" value="big" />big<br/>
    <input type="radio" name="type" value="medium" checked />medium<br/>
    <input type="radio" name="type" value="small"  />small<br/>
    </div>
    <!--需要引入jQuery文件-->
    <script type="text/javascript">
         alert($("[type=radio][name=type][checked]").val());
    </script>

  其中[type=radio][name=type][checked],就是对多个属性的同时使用,本例想打印type属性为radio、name属性为type、有checked属性(被选中)的元素的value值,需要引入jQuery文件。这个好像不用写得这么麻烦,突然忘了

  这些有的是css2,有的是css3,而且不一定各个浏览器通用,我只是知道有这么回事,没去分个类,原谅我白痴=_=

关键词: