我就是要用CSS如何实现九宫格图

我和你,或许分开才是最好的选择,那些曾经的过客,就当做最美丽的风景线,在以后的以后,我会好好坚强。

下图是手Q吃喝玩乐 好友去哪儿九宫格图的图示:

从上图我们可以分析出如下需求:

  • 图片大小自适应;
    图片个数不同时,图片按照指定方式排列;
    图片相邻处有1px空白间隙。

我们以最复杂的6图布局为例,一步一步来看如何以纯CSS实现。

1、float布局

最容易想到的,也是最简单的方案,就是 float 布局:

图片大小自适应:宽度百分比,高度使用 padding-top 百分比
图片个数不同时,图片按照指定方式排列:使用 nth-child 伪类指定不同情况下的元素大小
图片相邻处有1px空白间隙:使用 border-box + border模拟边框

这里父元素的高度未知,height使用百分比行不通,而padding的百分比值是依据父元素的宽度来计算的,我们可以使用padding-top撑开高度。

让我们一瞅伪码:

XHTML

XML/HTML Code复制内容到剪贴板
  1. <divclass="float">
  2. <divclass="item">1</div>
  3. ...
  4. <divclass="item">6</div>
  5. </div>

CSS

CSS Code复制内容到剪贴板
  1. .float{
  2. overflow:hidden;
  3. }
  4. .item{
  5. float:left;
  6. padding-top:33.3%;
  7. width:33.3%;
  8. border-right:1pxsolid#fff;
  9. border-top:1pxsolid#fff;
  10. }
  11. .item:nth-child(1){
  12. padding-top:66.6%;
  13. width:66.6%;
  14. }
  15. .item:nth-child(2),.item:nth-child(3),.item:nth-child(6){
  16. border-right:0none;
  17. }
  18. .item:nth-child(1),.item:nth-child(2){
  19. border-top:0none;
  20. }

实际效果并不理想,如下图:

可以看到 float 布局的优点是DOM结构十分简单,缺点是容易出现空白间隙错位,优缺点都十分明显,它更适用于js计算的版本。

2、flex布局

还有谁?flex!flex布局有以下重要特性:

  • 可以将 flex 布局下的元素展示在同一水平、垂直方向上;
    可以支持自动换行、换列(移动端-webkit-box暂不支持,好消息是从iOS9.2、Android4.4开始都支持新flex了);
    可以指定 flex 布局下的元素如何分配空间,可以让元素自动占满父元素剩余空间;
    可以指定 flex 布局下的元素的展示方向,排列方式。

这里面的子元素同一水平、垂直方向展示对我们很有帮助,它使我们更容易控制子元素的排列,而不会错位。

使用 flex 布局与 float 布局不同的地方在于,移动端目前主要还是-webkit-box,因此图片个数不同时,我们需要使用不同的html,组合出不同的块。

flex 布局上下划分

来,我们快动手分块吧!新解决方案出现导致的肾上腺素上升,使我们迫不及待使用了传统css文档流自上而下的方式来划分,我称为上下划分,如下图:

上面一块包含左侧1个2/3的大块,右侧2个1/3的小块,下面一块则是3个1/3的小块。

我们指定2/3的大块宽度是66.6%,1/3的小块宽度是33.3%(实际可以使用-webkit-box-flex来分配,这里为了下面的计算方便)。

来看下实际效果,你也可以猛击demo来查看源码:

demo中我们看到中间那条竖空白间隙错位了,为什么?按照预期我们上面块左侧宽度66.6%,下面块左侧宽度33.3% + 33.3%,两个宽度应该相等才对。

然而我们忽略了flex一个重要特性,子元素会自动占满父元素剩余空间,这时子元素宽度计算受flex控制,下面块的3个子元素宽度计算并非一定是相等的,会有些许差异,此时66.6% != 33.3% + 33.3%。

怎么破!别急,让我们冷静下来重新思考如何划分。

flex 布局左右划分

问题在于竖间隙涉及到的左右侧宽度计算不稳定,既然如此,我们可以考虑依据竖间隙左右划分,排除不稳定因素,如下图:

这样就解决了竖间隙错位问题,但我们依然有所担心,中间的横间隙会错位吗?我们来算一下。

整体父元素宽度确定,为W;

整体父元素高度由子元素撑开,不确定;

左侧大块高度:左侧flex父元素宽度(W * 66.6%) * 100% = W * 66.6%;

左侧小块高度:左侧flex父元素宽度( W * 66.6%) * 50% = W * 33.3%;

右侧小块高度:右侧flex父元素宽度( W * 33.3%) * 100% = W * 33.3%。

依然是66.6%与33.3% + 33.3%的等式,但这次高度计算会受 flex 影响吗?

不会,因为此时整体父元素的高度是不确定的,是由子元素内容撑开的,flex的高度也是由子元素来撑开的。

最终 66.6% === 33.3% + 33.3%

我们来看下伪码,猛击我看demo:

XHTML

XML/HTML Code复制内容到剪贴板
  1. <divclass="wrap-boxwrap-6">
  2. <divclass="flex-inner">
  3. <divclass="flex-box1flex-item"></div>
  4. <divclass="flex-box2">
  5. <divclass="flex-item"></div>
  6. <divclass="flex-item"></div>
  7. </div>
  8. </div>
  9. <divclass="flex-inner">
  10. <divclass="flex-item"></div>
  11. <divclass="flex-item"></div>
  12. <divclass="flex-item"></div>
  13. </div>
  14. </div>

CSS

CSS Code复制内容到剪贴板
  1. .wrap-box{
  2. display:-webkit-box;
  3. }
  4. .flex-inner{
  5. -webkit-box-flex:1;
  6. display:-webkit-box;
  7. }
  8. .flex-item{
  9. -webkit-box-flex:1;
  10. position:relative;
  11. }
  12. .wrap-6{
  13. -webkit-box-orient:horizontal;
  14. }
  15. .wrap-6.flex-inner{
  16. -webkit-box-flex:0;
  17. -webkit-box-orient:vertical;
  18. }
  19. .wrap-6.flex-inner:first-child{
  20. width:66.6%;
  21. }
  22. .wrap-6.flex-inner:last-child{
  23. width:33.3%;
  24. }
  25. .wrap-6.flex-item{
  26. padding-top:100%;
  27. }
  28. .wrap-6.flex-box2.flex-item{
  29. padding-top:50%;
  30. }
  31. .wrap-6.flex-box2{
  32. display:-webkit-box;
  33. -webkit-box-orient:horizontal;
  34. }
  35. .wrap-6.flex-inner:first-child,
  36. .wrap-6.flex-box2.flex-item:first-child{
  37. margin-right:1px;
  38. }
  39. .wrap-6.flex-box1,
  40. .wrap-6.flex-inner:last-child.flex-item:first-child,
  41. .wrap-6.flex-inner:last-child.flex-item:nth-child(2){
  42. margin-bottom:1px;
  43. }

实际效果:

以上就是本文的全部内容,希望对大家的学习有所帮助。

您可能有感兴趣的文章
css中的content: "." 有什么用?为什么要用他?

css让页脚保持在底部位置的四种方案

CSS如何使用Flex和Grid布局如何实现3D骰子

Flex布局史上最简单使用语法教程

新的CSS 伪类函数 :is() 和 :where()示例详解