CSS Secret——Structure & Layout

根据内容指定宽度

假如我们有如下结构:

<figure>
    <img src="img/adamcatlace.jpg" />
    <figcaption>
        The great Sir Adam Catlace was named after  Countess Ada Lovelace, the first programmer.
    </figcaption>
</figure>

我们想让文字的最大宽度和图片同宽,图片的宽度并不是固定的。
使用新的 CSS Intrinsic & Extrinsic Sizing Module Level 3 中width属性值min-content就可以做到。

figure { width: min-content; margin: auto; }

关于表格的fixed布局

表格布局table-layout的默认值是auto,这个值时表格的列宽并不是很稳定,它会根据表格的所有内容来调整表格的列宽,而且就算你显示指定了列宽,在布局冲突的时候(比如列宽加起来超了),你指定的列宽是不会被满足的,最多是按比例。text-overflow: ellipsis也不会起作用。图片太大了也会撑开表格。
在fixed的情况下,表格的列宽更加可控,首先你要显示的指定整个表的宽度,列宽度在不指定的情况下会自动均分而与表中内容无关;有指定的列宽就按指定的,剩下的均分,全部指定就按所有的,和总宽度冲突也不会管。text-overflow和其他overflow就正常使用了。

因同类元素总数而异的样式

比如一个列表中有10个一下的项,字号可以大一点,10个以上就小一点。或者项多了就省略每项中的某些内容。

一个

针对只有一个的可以使用:

#styleWithNum li:only-child{
  color:red;
}

当然:only-of-type也同样适用,下面就都以child系举例。
上面的还可以用这个替代:

#styleWithNum li:first-child:last-child{
  color:red;
}

也就是这个:

#styleWithNum li:first-child:nth-last-child(1){
  color:red;
}

啊~这意味着我们在找一个元素,他是第一个元素,同时也是倒数第1个元素。看到这里你会不会想,如果我把1改成3呢?

指定数目的所有同类

那就意味着我们在找一个元素,他是第一个元素,同时也是倒数第3个元素,如果有这个元素,那就意味着我们的同类元素的数目正好是3个!
我们可以利用着个来选中所有3个元素:

li:first-child:nth-last-child(3),
li:first-child:nth-last-child(3) ~ li {
    /* Target list items iff the list
       contains exactly three items */
}

使用SCSS来简化一点:

/* Define mixin */
@mixin n-items($n) {
  &:first-child:nth-last-child(#{$n}),
  &:first-child:nth-last-child(#{$n}) ~ & {
    @content;
  }
}
/* Use it like so: */
li {
  @include n-items(3) {
    color:blue;
  }
}

注意,这里有个小问题,使用时li前面不能有其他选择符,否则编译出来是这样的:

#styleWithNum li:first-child:nth-last-child(3),
#styleWithNum li:first-child:nth-last-child(3) ~ #styleWithNum li {
  color: blue;
}

而~后面识别不出层级选择的。

当同类元素数目大于某个值时,选中所有同类元素

这里利用的是:nth-child(n+b)会选中第b个及其以后的元素:

li:first-child:nth-last-child(n+4),
li:first-child:nth-last-child(n+4) ~ li {
    /* Target list items iff the list
       contains at least four items */
}

当同类元素数目小于某个值时,选中所有同类元素

利用:nth-child(-n+b)会选中第b个及其以前的元素:

li:first-child:nth-last-child(-n+4),
li:first-child:nth-last-child(-n+4) ~ li {
    /* Target list items iff the list
       contains at most four items */
}

当同类元素数目在某个范围时,选中所有同类元素

结合上面两个:

li:first-child:nth-last-child(n+2):nth-last-child(-n+6),
li:first-child:nth-last-child(n+2):nth-last-child(-n+6) ~ li {
    /* Target list items iff the list
       contains 2-6 items */
}

背景铺满,内容有最大宽度并居中

这样的布局是非常普遍的,一般使用一个元素铺满宽度,里面再放一个元素规定最大宽度,左右外边距auto。现在我们只用一个元素就可以实现:

#footer {
  padding: 1em;
  padding: 1em calc(50% - 450px);
  background: #333;
  color: #ffffff;
}

这里使用了calc这个函数,在屏幕宽度大于900px时,padding两边相等会使内容居中且宽度永远为900。在宽度小于900时,padding为负的,但是padding不允许为负,所以就是0,如果这个不可接受就用媒体查询吧。

垂直居中

老大难问题

绝对定位

这个适合在一个未知大小的元素中居中一个已知大小的元素。

position: absolute;
top:50%;
left:50%;
margin-left:ckildWidth/2;
margin-top:childHeight/2;

表格

利用表格,可以在一个未知大小的元素中居中一个未知大小的元素。

<table style="width: 100%;">
    <tr>
        <td style="text-align: center; vertical-align: middle;">
            Unknown stuff to be centered.
        </td>
    </tr>
</table>

如果你不想用表格元素,display中表格相关的属性可以达到同样的效果。

<div class="vertical1">
    <div>
        Unknown stuff to be centered.
    </div>
</div>
.vertical1 {
  display: table;
  width: 100%;
  height: 100px;
  background-color: #0074d9;
  div {
    display: table-cell;
    text-align: center;
    vertical-align: middle;
    background-color: #2d672d;
    background-clip: content-box;
  }
}

但是这样做限制很多,比如居中元素的宽度其实你是控制不了的,会是100%。如果你想在居中元素中放一个块级元素,它也会表现的像是table-cell。

利用垂直居中的伪元素

这个方法适合父元素和子元素的宽高都不定的情况。比表格的办法先进。
HTML的结构也很明朗。

<div class="vertical2">
    <div class="centered">
        <p>If we set up a "ghost" element inside the parent that is 100% height, then we vertical-align: middle both that and the element to be centered, we get the same effect.</p>
    </div>
</div>

伪元素高度为100%, display: inline-block,且垂直居中。要居中的元素也是 display: inline-block垂直居中。

.vertical2 {
  text-align: center;
  background: #c0c0c0;
  border: #a0a0a0 solid 1px;
  margin: 20px;
  height:300px;
  &:before {
    content: '';
    /*   content: '';
      margin-left: -0.25em; */
    display: inline-block;
    height: 100%;
    vertical-align: middle;
  }

  .centered {
    display: inline-block;
    vertical-align: middle;
    width: 300px;
    padding: 10px 15px;
    border: #a0a0a0 solid 1px;
    background: #f5f5f5;
  }
}

利用transform

之前绝对定位的问题是使用了与子元素长宽相关的外边距值,这个值如果使用百分比的话是相对父元素来说的,如果我们可以找到相对子元素本身移动50%的办法就好了。
transform正好就是这样。

<div class="vertical3">
    <div class="centered">
        <p>之前绝对定位的问题是使用了与子元素长宽相关的外边距值,这个值如果使用百分比的话是相对父元素来说的,如果我们可以找到相对子元素本身移动50%的办法就好了。
            transform正好就是这样。</p>
    </div>
</div>
.vertical3 {
  position: relative;
  height:300px;
  .centered {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
}

终极方法: Flexbox

前面的方法之所以还存在是因为这个的浏览器支持并不太好,否则。。。不说了。。。放上代码你感受下:

<div class="vertical4">
    <div class="centered">
        <p>终极方法:flex</p>
    </div>
</div>
.vertical4 {
  background-color: #449d44;
  display: flex;
  height:200px;
  .centered {
    margin: auto;
    max-width:200px;
    background-color:#0074d9;
  }
}

当使用 Flexbox 时,其子元素margin:auto上下左右都均分。
而且它还可以用来居中匿名元素:

<div class="vertical5">
    终极方法:flex——居中匿名text
</div>
.vertical5 {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 18em;
  height: 10em;
  background-color: #0074d9;
}

未来

现在在计划中的 CSS Box Alignment Level 3 中有个:

align-self: center;

这东西一写,所有的都居中了。。。。

页脚

我们一般写页脚时有两种形式,一种是不管页面内容多长多短,都显示在屏幕下方的。这种直接用position:fixed给定在视口的下面就好了。
另一种是在页面内容加页脚的总高度不超过视口的时候让页脚固定在底部,在超过视口时滚动到底部看到页脚。这个就有点麻烦了。

固定高度的页脚

页脚高度固定时可以给页脚上面的所有内容规定一个最小高度,这个高度的值是视口高度减去页脚的高度。

<main>

</main>
<footer></footer>
main { 
    min-height: calc(100vh - footerHeight); 
}

FlexBox

假设我们的页面结构是这样的:

<body class="footerTest">
    <header>
        <h1>页脚测试</h1>
    </header>
    <main>
        <p>wawawaawaw</p>
    </main>
    <footer>
        <p>© 2015 No rights reserved.</p>
        <p>balalala</p>
    </footer>

</body>

首先body要有一个填满视口的最小高度,display需要是flex,由于下面有3个元素,他们要排成一列,所以还有 flex-flow: column。

.footerTest{
  display: flex;
  flex-flow: column;
  min-height: 100vh;
  margin: 0;
}

下一步就是使main有一个不为0的flex值。

.footerTest header{
  background-color: #0074d9;
  color: #FFF;
  text-align: center;
}
.footerTest main{
  height: 500px;
  background-color: #449d44;
  flex: 1;
}
.footerTest footer{
  background-color: #333;
  color:#fff;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值