7.4 图书区

接下来,有四本图书封面的展示区位于页面底部。为了给这一部分增添趣味性,我们要使用弹出层和旋转文本。先看HTML标记。

  1. <section id="book_area">
  2. <article class="left">
  3. <div class="inner">
  4. <h3>HTML5 + CSS3</h3><!-- 要旋转的文字 -->
  5. <img src="images/stylin_cover.png" alt="Stylin' with CSS cover" />
  6. <aside> <!-- 弹出层 -->
  7. <ol>
  8. <li><a href="#">Download the Code</a></li>
  9. <li><a href="#">Table of Contents</a></li>
  10. <li><a href="#">Buy this Book</a></li>
  11. </ol>
  12. </aside>
  13. </div>
  14. </article>
  15. <!-- 另外三本图书的标记也一样 -->
  16. </section>

怎么样,HTML代码极其简单,同样的标记重复四次,就是四本书。下面来看看相关的CSS吧,先看看布局和旋转文本的样式,然后再看弹出层的样式。

  1. section#book_area { /*与布局同宽*/
  2. clear:both;
  3. border-radius:20px 0px 20px 0px;
  4. border:1px solid #f58c21;
  5. margin:8px 0 16px; /*上下间距*/
  6. overflow:hidden;
  7. }
  8. #book_area article { /*四本书四栏*/
  9. float:left;
  10. width:25%;
  11. padding:10px 0;
  12. background:none;
  13. }
  14. #book_area article .inner { /*封面外包装*/
  15. position:relative; /*为弹出层提供定位上下文*/
  16. width:140px; /*包装每一本书*/
  17. margin:0 auto; /*在各自article元素内居中每一本书*/
  18. }
  19. #book_area .inner h3 { /*旋转文字*/
  20. position:absolute;
  21. width:160px;
  22. left:112%; bottom:5px; /*把文字定位在图书右侧*/
  23. transform:rotate(-90deg); /*旋转文字需要使用带厂商前缀的属性*/
  24. transform-origin:left bottom; /*设定旋转中心点,需要带厂商前缀的属性*/
  25. color:#ccc;
  26. font-size:1.4em;
  27. font-family:Lato, helvetica, sans-serif;
  28. font-style:normal;
  29. font-weight:900;
  30. text-align:left;
  31. }
  32. #book_area article.right:last-child h3 { left:85%; } /*较窄的封面需要不同的偏移量*/
  33. #book_area article img { box-shadow: 0 12px 8px -9px #555; }/*封面阴影*/

在与布局同宽的section#book_area元素中,我们浮动了四个article元素,每个元素的宽度都设定为25%。在这四个article中,分别使用一个有宽度的内部div来包含图书封面。这样就可以为图书封面之间添加适当的间距,如图7-14所示。接下来要做成弹出层的aside元素目前还处于隐藏状态。

enter image description here图7-14 图书区的每本书封面的右侧都有自己的描述性标题

旋转文字是用CSS3的transform属性的两个函数实现的。第一个函数是transform-origin,用于把旋转变换的原点设定为h3元素盒子的左下角。这里的原点指的是旋转的中心点,就好像我在那个地方插进去一根大头针一样。然后用transformrotate函数把h3元素旋转90度,最后再将它们向上移动5像素。关于transform属性的更多介绍,请参考附注栏“CSS3变换”。如果觉得不解渴,可以购买我的电子书Visual Stylin' with CSS :)

CSS3变换

如果你用过Adobe Illustrator或Fireworks等平面图形设计软件,可能知道对文本和其他元素进行旋转、缩放和斜切变换。现在,通过CSS3变换在浏览器中也能实现同样的效果了(如图7-15所示)。

CSS3为变换规定了两个属性:transformtransform-origin。先说说transform

transform属性能够调用函数,调用不同的变换函数可以实现不同形式的变换,而通过传入的参数值可以控制变换的结果。通过transform属性调用变换函数的语法如下:

  1. transform:函数名(数值或xy值);

以下是CSS3规定的变换函数。

  • scale:用于放大或缩小元素(指定大于1的值放大元素,小于1的值缩小元素),如transform:scale(1.5)
  • rotate:根据指定的度数旋转元素(正值顺时针旋转,负值逆时针旋转),如transform:rotate(-30deg)
  • skew:让元素在x轴和y轴方向倾斜(只指定一个值,y轴不受影响),如transform:skew(5deg, 50deg)
  • translate:根据指定的距离沿x轴和y轴平移对象(很像相对定位,因为对象初始占据的空间会保留),如transform:translate(-50px, 20px)

transform-origin属性设定元素围绕其变换的原点。默认情况下,这个点是元素垂直和水平方向的中心点。因此,如果你旋转元素而未另行指定原点,就会像在元素中心点插进一根大头针一样,然后元素围绕该点旋转。可以使用transform-origin属性及位置关键字(leftcenterrighttopbottom等)另行设定原点,而使用正、负数字甚至可以把原点设定到元素边界之外。

Blockquote 图7-15 几个变换的例子

现在该为每本书添加弹出层了。以第6章那个弹出层示例为基础,还要进行两点改进。首先,让页面右侧图书的弹出层显示在封面图片左侧,以免出现在右侧被浏览器窗口“切掉”。其次,把箭头图形放在弹出层一边,让人感觉它也是弹出层边框的一部分。经验告诉我们,像这种看似不起眼但却很有意思的改进,往往要编写很多代码。

如果你现在看看前面的标记,会发现我已经给包含图书的article元素分别添加了leftright类,以便分别设定出现在封面右侧和左侧的弹出层和箭头。下面就是CSS啦!

  1. #book_area article aside { /*弹出层共享样式开始*/
  2. display:none; /*隐藏弹出层*/
  3. position:absolute; /*相对于包含图片的内部div*/
  4. z-index:2;
  5. width:200px; /*弹出层宽度*/
  6. background:#fff;
  7. padding:10px 2px 5px; /*弹出层内容边距*/
  8. border:2px solid #f58c21;
  9. border-radius:10px 0px 10px 0px;
  10. box-shadow:4px 4px 16px #555;
  11. color:#555;
  12. font-family:"Source Sans Pro", helvetica, sans-serif;
  13. font-size:.8em;
  14. line-height:1.5em;
  15. }
  16. #book_area article:hover aside { display:block; }/*鼠标悬停于封面时显示弹出层*/
  17. #book_area article aside li {
  18. padding:.25em 0 .75em 1em; /*列表项的垂直间距和左边距*/
  19. list-style-type:none; /*去掉默认的项目符号*/
  20. line-height:1.2em;
  21. }
  22. #book_area article aside li a { /*链接文本*/
  23. text-decoration:none;
  24. font-size:1.2em;
  25. color:#616161;
  26. }
  27. #book_area article aside li a:hover { /*悬停时突显链接*/
  28. color:#333;
  29. } /*弹出层共享样式结束*/
  30. #book_area article.left aside {/*左侧两本书*/
  31. left:84%; top:14px; /* 把弹出层定位在图片右侧*/
  32. }
  33. #book_area article.right aside {/*右侧两本书*/
  34. right:84%; top:14px;/*把弹出层定位在图片左侧*/
  35. }
  36. #book_area article aside:after { /*橙色三角形*/
  37. content:""; /*需要有内容,这里是一个空字符串*/
  38. position:absolute; /*相对于弹出层定位*/
  39. top:33px;
  40. border:12px solid;
  41. height:0px; width:0px; /*收缩边框创造三角形*/
  42. }
  43. #book_area article.left aside:after { /*左侧图书弹出层的三角形定位及颜色*/
  44. right:100%;
  45. border-color:transparent #f58c21 transparent transparent;
  46. }
  47. #book_area article.right aside:after { /*右侧图书弹出层的三角形定位及颜色*/
  48. left:100%;
  49. border-color:transparent transparent transparent #f58c21;
  50. }
  51. #book_area article aside:before { /*白色三角形*/
  52. content:""; /*需要有内容,这里是一个空字符串*/
  53. position:absolute; /*相对于弹出层定位*/
  54. border:8px solid;
  55. height:0px; width:0px; /*收缩边框创造三角形*/
  56. z-index:100; /*保证白色三角形在最前面*/
  57. top:37px;
  58. }
  59. #book_area article.left aside:before { /*左侧图书白色三角形的样式、位置和颜色*/
  60. right:100%;
  61. border-color:transparent white transparent transparent;
  62. }
  63. #book_area article.right aside:before { /*右侧图书白色三角形的样式、位置和颜色*/
  64. left:100%;
  65. border-color:transparent transparent transparent white;
  66. }

弹出层是一个绝对定位的元素,它相对于包含每本书的内部div定位。在第6章那个弹出层的例子中,我们只把红色三角形定位在弹出层的一边(参见图6-24)。而在这个例子中,我们大幅度地改进了这个效果,弹出层似乎是把边框给向外挤出了一个尖尖的指针,如图7-16所示。这个效果是通过在橙色三角形上面叠加另外一个更小的白色(与弹出层背景色相同)的三角形,并将它们垂直的边对齐实现的。这样就用橙色三角形创造了边框的效果。

enter image description here图7-16 节省空间的弹出层提供每本书的链接和额外信息

添加白色三角形使用的是::before伪元素,添加橙色三角形使用的是::after伪元素,而绝对定位和z-index属性则将它们在弹出层边框上精确地对齐。这个结果非常自然,弹出层及其指针浑然一体。

这个例子中容易搞混的地方是记住哪个弹出层在左,哪个弹出层在右。比如,左侧两本书的弹出层位于它们封面的右侧,而这两个弹出层的指针三角形则位于弹出层左侧。右侧两本书的情况恰好相反。

通过这个例子,我们又重温了前面提到的自上而下的方法。前面代码中的注释已经明确告诉你了,首先是所有弹出层共享的样式,包括大小、内边距、边框、颜色和内容等样式。其次是把前两本书的弹出层定位在图片右侧的规则,以及把后两本书的弹出层定位在图片左侧的规则。随后是所有图书弹出层指针三角形共享的样式。再接着是左侧两本书弹出层三角形的样式,以及右侧两本书弹出层三角形的样式。

这种编码原则简称为DRY(don't repeat yourself),即“不要重复自己”。目标是让每一个效果最终都有“独立且权威的来源”。

尽管一两句话不能解释清楚,但这些代码逻辑上是前后相继的,而且避免了那种每个弹出层都完全重写一遍规则的做法。我想,这个例子很值得大家花点时间深入研究、认真体会。如果能自己从头写出这个例子来,对理解其中的奥妙绝对是有帮助的。这种前后相继的代码组织技巧,能够把为多个元素编码的工作分解成相同的部分和不同的部分。最重要的是,它能为你自己和他人将来的维护工作提供方便。

好了,这个页面就剩最后的页脚啦。