跳转到主要内容
大漠 提交于 8 July 2011

龙兄多次邀请我这位菜鸟来花园写点东西,一直不敢,今天鼓起勇气来这里乱侃,说得不好大家不要见笑。今天我主要想跟大家说的是在Drupal中如何避免重复列末尾的margin。废不多说,就开始吧!

在页面中创建列表项,大家并不陌生,常见的一种就是产品展示页面,制作过程中大家肯定碰到了每行最后一个列表项的margin不太好处理。当然如果是在静态页面中,这样的问题很轻松解决,在每行的最后一列加上一个class名,比如last,并定义相应的样式就完全搞定了;但是对于一个CMS的动态网站,比如我在工作中常碰到的Drupal,在Drupal中对产品进行展示布局,我就无法在相应的行中最后一列加上class名,从而让我无法去除他的margin值。换句话说,在一个动态网站中,我无法修改行中最后一列的margin值,从而使用最后一列多出了不想要的margin。下面这个例子是我在Drupal最常见的一种如下:

此时列表父元素(也就是圆框部分)设置了具体的宽度时,每行的第四个产品列表就会相应的被移到下一行,比如说我们此时的列表父元素总宽度为245px,而每个产品的尺寸为50px*50px,并且每个产品加上一个15px的marin-right,依此计算,一行放置四个产品总宽度就需要:50px*4+4*15=260px,此时比总宽度多出了15px的距离。所以无法放置四个产品,如下图所示:

看到上面,大家会说,在第四个,第八个,第4个的N倍数上加上一个class名,如果是静态页面是很好处理,今天我不想说在静态页面的处理方法,因为大家都知道,我说了浪费大家时间,我想说的是在CMS的Drupal下如何处理这样的bug。前面也说过了,一般情况下是可以到指定列上设置一个class,然后在样式中设置样式,但在Drupal中无法轻意做到给相应列加上class名,特别是对于我这样不懂程序的themer来说,相当的困难,我想部分玩Drupal的themer跟我肯定是有类似的遭遇。那么现在开始不要怕了,找到救我们的办法,具体的实现方法就跟着我往下看吧。

解决方法的思路:通过在列表外加上一个div将其包起来,并加上overflow:hidden将其多出来的margin进行隐藏。这样说可能并不清楚,现在将上面的一句话拆分开来说,首先按正常的列表项宽度并加上其各自的margin计算出列表宽度值;其次在列表外面加一个div,并将其宽度设置为列表宽度减去最后一个margin-right,并加上一个overflow:hidden属性,我们来看其实现示意图:

下面一起来看看具体看他是如何实现的,现来看其HTML代码:

   <div class="views block">
      <ul class="listItem clearfix">
	<li><a href="#"><img src="images/product.jpg" alt="" /></a></li>
	<li><a href="#"><img src="images/product.jpg" alt="" /></a></li>
	<li><a href="#"><img src="images/product.jpg" alt="" /></a></li>
	<li><a href="#"><img src="images/product.jpg" alt="" /></a></li>
	<li><a href="#"><img src="images/product.jpg" alt="" /></a></li>
	<li><a href="#"><img src="images/product.jpg" alt="" /></a></li>
	<li><a href="#"><img src="images/product.jpg" alt="" /></a></li>
	<li><a href="#"><img src="images/product.jpg" alt="" /></a></li>
     </ul>
   </div>

上面的结构在CMS系统中是常见的,比如说Drupal中,玩Drupal的一定不会陌生,他是一个views模块自动生成的一个列表结构,如果不是CMS,而是自己写模板的,我也建议在列表外加上一具容器“<div>...</div>”。因为我们解决这个多余margin的原理就是在列表增加一个容器,并设置一个宽度,用来隐藏那个多余的margin。

CSS Code:

   .views {
      -moz-border-radius: 5px;
      -webkit-border-radius: 5px;
      border-radius: 5px;
      -moz-box-shadow: 0 0 3px #ccc;
      -webkit-box-shadow: 0 0 3px #ccc;
      box-shadow: 0 0 3px #ccc;
      padding: 10px;
      width: 245px;
      overflow: hidden;
   }
		
   .views ul {
      width: 260px;
      float: left;
   }
					
  .views li {
      float: left;
      display: inline;
      width: 50px;
      margin: 7px 15px 7px 0;
   }

样式中关键的两步就是计算列表宽度和列表容器的宽度(在这里就是列表ul.listItem的宽度和列表容器div.views的宽度),那么计算他们的宽度有两种方法:

第一种就是已知列表的宽度和margin,这样我们就可以得到列表ul.listItem和列表容器div.views的宽度,其计算方法如下:

   列表的宽度=列表项的宽度 X 列表项数量 + (列表项数量) X margin值;
   列表容器宽度= 列表的宽度 - 最后一个margin值;

就如我们这个实例来说,li的宽度是50px;而一行是放置4个列表项,并且margin-right:15px,而margin-left:0;按上面的计算方法分别得到列表总宽度和列表容器总宽度:

   列表宽度=50px * 4 + (4) * 15px = 260px;
   列表容器宽度= 260px - 15px = 245px;

第二种方法就是已知列表容器总宽度,并知道列表项个数以及列表项的margin值;那么其计算列表宽度和列表项的宽度如下:

   列表宽度=列表容器宽度 + 列表项最后一个margin-rigth值;
   列表项的宽度=列表宽度/列表项个数-列表的margin-right值;

拿此例来说,我们只知道列表容器总宽度为245px;并且每个列表项的margin-right值为15px;根据上面的公式就可以分别得到列表宽度和列表项宽度:

   列表宽度 = 145px + 15px =260px;
   列表项宽度 = 260px/4-15px=50px;

我把上面两种方法叫做反算宽度和顺算宽度法,不管使用哪种方法得到相应值后,最为关键的是需要在列表元素设置总宽度,并在列表容器元素上加上一个overflow: hidden属性,用来隐藏列表项溢出的margin-right值。

上面我们只是介绍了如何处理最好一个多余的margin-right值,而且在计算宽度值时,没有计算其列表项的padding和border值,如果你在实际应用中如果涉及到了padding和border那么你在计算时需要考虑到这两个值。不然按上面的运用会出问题。另外我个人认为最好使用反算法来计算列表的宽度和列表容器的宽度,这样更不会出问题。

最终效果如下所示:

这里我们主要使用的一个假象用来避免重复列多余的margin值,在现代浏览器中还有一种更佳的处理方法,那就是CSS3的“:nth-child 【:nth-child() 伪类允许你定位某个上级元素的一个或多个特定的子元素。】”伪类选择器来实现,就拿我们本列来说,在现代浏览器中我们不需要去考虑那么多,直接使用“:nth-child”就可以实现:

   .views {
      border: 1px solid #ccc;
      -moz-border-radius: 5px;
      -webkit-border-radius: 5px;
      border-radius: 5px;
      -moz-box-shadow: 0 0 3px #ccc;
      -webkit-box-shadow: 0 0 3px #ccc;
      box-shadow: 0 0 3px #ccc;
      padding: 10px;
      width: 245px;
    }
					
    .views li {
      float: left;
      display: inline;
      width: 50px;
      margin: 7px 15px 7px 0;
   }
				
   .views li:nth-child(4n){
      margin-right: 0;
   }

效果如下所示:

此例中采用了一个“.views li:nth-child(4n)”选择器,他所表示的意思就是列表元素数中的4的倍数的列表项将被选中,此时并把其margin-right值设置为“0”。如此一来刚好达到我们所需要的效果。大家可以对比一下,看看其效果是否一致。这种实现方法唯一让我们感到头痛的就是那个让人蛋疼的IE浏览器,因为IE9以下版本的浏览是不支持CSS3的伪类选择器。有关于CSS3的伪类选择器的具体使用方法,请大家观注本站的更新,W3CPLUS将会在后面专门介绍CSS3的使用方法。

关于如何在CMS动态网站中清除重复列多余的margin值,就介绍到这了,上面两种方法具体如何使用,大家可以根据自己的项目需求选择。如果大家有更好的方法,记得和我一起分享。

说到这里就差不多完了,最后向大家介绍一下我,我刚学drupal不久,是龙马和为之带出来的,网上朋友送名“大漠”。只懂一点drupal的theme,说得简单一点就只会一点css,希望大家以后多多指点,更希望能和大家一起进步。要是对“大漠”写的东西,请狠狠的点击W3CPLUS。这个是"大漠"的blog,当然如需转载也烦请注明出自花园或W3CPLUS。很乐意与大家分享这方面的知识

标签