阅读 5515

移动端布局面试题 全面考察你的CSS功底(居中篇)

前言

由于移动互联网的飞速发展,现在基本没有哪个前端说自己只开发 PC 端,移动端什么的我不管。

甚至好多前端主要的工作内容就是开发移动端,因为移动端的内容五花八门:微信小程序、支付宝小程序、京东小程序、快应用、微信公众平台、微信小游戏、混合App、H5等…

打开招聘软件,可以看到目前的岗位对前端的要求是越来越高了,上天入地无所不能,屏幕前的你也可以打开软件看一眼要求,是不是至少都有类似这么几条中的一两个:熟练掌握移动端前端技术、有微信小程序开发经验优先、有混合App开发经验优先,即使不是那种专门做移动端网站的公司,有不少也都写着会移动端优先…

所以移动端的布局就至关重要了,因为无论一个网站的页面背后有着多么复杂的交互逻辑、多庞大的用户量、多么海量的数据、多么高的并发… 它终究还是得有个页面吧!不能让用户一访问网站就直接给人家看数据库吧!

有人的地方就有江湖 有页面的地方就有布局

布局可不仅仅只是把数据整齐的罗列在页面上这么简单,一个合适的布局可以令用户的操作非常顺畅。同时在不同的场景下也应选择不同的布局,如果选错布局的话很可能会导致用户对页面的操作不那么的丝滑,哪怕最初呈现出来的数据都是一样的。

由于移动端的屏幕并不像电脑屏幕那么大,而且长宽比也有很大的区别,所以造就了移动端布局与 PC 端布局有着很大的不同,那么接下来我们就来看一下各式各样的常见布局。

居中布局

其实居中布局大家在日常生活中基本都见过,只是当时没怎么留意罢了。

没给用户留下深刻印象的布局反而是好布局,因为用户的注意力都在内容上了,证明此时的布局令用户操作顺畅。

而给用户留下印象的布局一般就不太好了(一些与众不同的炫酷布局除外):

这个按钮怎么放这了,我都误碰好几次了;关闭按钮在哪呢?怎么关啊这个;这个商品的简介在哪呢?应该点哪购买啊?这个布局怎么这么乱看的我都晕了,哎算了算了,以后不来这个网站了……

不同的布局用来对应不同的场景,用对场景的话会令用户的操作比较舒服顺畅,但用错场景的话用户可能会有些懵,不利于引导用户按自己想要的方式去操作。

这种布局是主内容处于页面的正中央位置,常见于登录、注册、提示用户、或点击头像查看大图等场景,通常会添加一层灰色的透明遮罩:

这么做的目的除了突出主题之外,还有一个比较重要的点就是可以令用户感觉到自己并没有离开当前页面,只不过是在当前页面中出现了一个小框而已,这样可以有效减少用户的陌生感。

不仅如此,居中布局还能够有效引导用户进行自己希望用户所进行的操作,用强烈的对比感去引导用户:

利用CSS库实现

借助市面上已有的 CSS 库,我们可以很轻易的做到居中布局,尤其是可以用到中文关键字,这非常有利于我们的记忆,它就是 chinese-layout

然后我们再用一个中文渐变色的 CSS 库来美化我们的界面:chinese-gradient

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <!-- 在这里用link标签引入中文布局 -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/chinese-layout">

  <!-- 在这里用link标签引入中文渐变色 -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/chinese-gradient">
  <style>
    /* 清除默认样式 */
    * { padding: 0; margin: 0; }

    /* 令html和body全屏显示 */
    html, body { height: 100%; }

    body {
      /* 先在父元素上设置grid布局 */
      display: grid;
      grid: var(--居中);

      /* 给个好看的渐变色 */
      background: var(--霾灰);
    } 

    .center {
      /* 指定子元素在中心位置 */
      grid-area: 中;

      /* 给子元素设置宽高,不然宽高为0导致什么也看不见 */
      width: 150px;
      height: 150px;

      /* 给一个好看的背景色 */
      background: var(--胭脂粉);
    }
  </style>
</head>
<body>
  <div class="center"></div>
</body>
</html>
复制代码

运行结果:

绝对定位实现

居中布局通常分为两种,一种是固定宽高,另一种是非固定宽高。

固定宽高很好理解,顾名思义就是宽高都写死。 而非固定宽高通常都是靠里面的内容来撑起盒子的高度,内容时多时少。

这两种方式也造就了不一样的技术实现,绝对定位法适合固定宽高:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    /* 清除默认样式 */
    * { padding: 0; margin: 0; }

    /* 令html和body全屏显示, 并有一个灰色背景 */
    html, body { height: 100%; background: gray; }

    /* 先在父元素上设置相对定位 */
    body { position: relative } 

    .center {
      /* 绝对定位 */
      position: absolute;

      /* 上下左右全部为0 */
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;

      /* 给定宽高 */
      width: 70%;
      height: 25%;

      /* 令外边距自动填充 */
      margin: auto;

      /* 白色背景 */
      background: white;
    }
  </style>
</head>
<body>
  <div class="center"></div>
</body>
</html>
复制代码

运行结果:

  • 如果不给定宽高,盒子将会和父元素一样大,因为绝对定位上下左右都是 0,意为紧贴着父元素的边。
  • 给了固定宽高,但没写 margin 的话盒子会固定在左上角,因为 top 和 left 的优先级更高。
  • 给了 margin: auto; 的话,浏览器会自动填充边距,令其居中。
  • 此种实现方式优点是兼容性很好,几乎没用到任何 CSS 的新特性,全部都是经典属性。

绝对定位 + 负边距

此种方法也是适用于固定宽高:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    /* 清除默认样式 */
    * { padding: 0; margin: 0; }

    /* 令html和body全屏显示, 并有一个灰色背景 */
    html, body { height: 100%; background: gray; }

    /* 先在父元素上设置相对定位 */
    body { position: relative }

    .center {
      /* 绝对定位 */
      position: absolute;

      /* 上方和左方为50% */
      top: 50%;
      left: 50%;

      /* 给定宽高 */
      width: 300px;
      height: 200px;

      /* 上外边距为负的给定高度的一半 */
      margin-top: -100px;

      /* 左外边距为负的给定宽度的一半 */
      margin-left: -150px;

      /* 白色背景 */
      background: white;
    }
  </style>
</head>
<body>
  <div class="center"></div>
</body>
</html>
复制代码

运行结果:

⚠️ 注意,"绝对定位+负边距"这种方法不适合那种宽百分之多少、高百分之多少这种相对单位,取而代之的是具体的数值。

因为边距的百分比和宽高的百分比相对的不是同一参考物,它是相对于父元素的宽来计算的,这点要注意。

绝对定位 + 平移

有时中间盒子的内容是要靠后台传过来的数据决定的,如果写死的话,当数据较多时就会发生溢出,数据较少时又会空出一大片,所以我们需要一种更加智能的方式来实现居中布局。

绝对定位 + 平移绝对定位 + 负边距的改进版,那么具体都改进了哪些方面呢? 负边距的百分比并不是相对于自身,而是相对于父元素,所以只能写具体的像素值,显得不够智能。

而平移相对于自身,只需要无脑写 -50% 就可以了:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    /* 清除默认样式 */
    * { padding: 0; margin: 0; }

    /* 令html和body全屏显示, 并有一个灰色背景 */
    html, body { height: 100%; background: gray; }

    /* 先在父元素上设置相对定位 */
    body { position: relative }

    .center {
      /* 绝对定位 */
      position: absolute;

      /* 上方和左方为50% */
      top: 50%;
      left: 50%;

      /* 不用给宽高,但是可以给个内边距防止内容与盒子过于贴合 */
      padding: 10px;

      /* 这个50%是相对于自身宽高而言的 */
      transform: translate(-50%, -50%);

      /* 白色背景 */
      background: white;
    }
  </style>
</head>
<body>
  <div class="center">
    用内容撑开盒子
  </div>
</body>
</html>
复制代码

运行结果:

  • margin 的百分比是相对于父元素的宽;
  • translate 函数的百分比是相对于自身;
  • 不仅适用于未知宽高,也同样适用于固定宽高的居中布局。

网格 Grid 实现

大家可能或多或少听过一些 Grid 的大名,深入了解过的人会觉得它很强大,但没深入了解过的人对它的印象可能就是:兼容性不好

但随着时间的推移,在移动端只要不考虑特别低版本的手机的话基本上都可以用了。

即使你对 Grid 没什么兴趣,觉得在移动端用 Flex 就已经足够了的。把它最简单的用法记住了也不会费太大劲。因为毕竟如果你能给面试官写出一个最新的技术,面试官也会对你刮目相看的:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    /* 清除默认样式 */
    * { padding: 0; margin: 0; }

    /* 令html和body全屏显示, 并有一个灰色背景 */
    html, body { height: 100%; background: gray; }

    /* 中央盒子的直接父元素 */
    body {
      /* 令其变成网格布局 */
      display: grid;

      /* 令其子元素居中 */
      place-items: center;
    }

    .center {
	  /* 不用给宽高,但是可以给个内边距防止内容与盒子过于贴合 */
      padding: 10px;
      
      /* 白色背景 */
      background: white;
    }
  </style>
</head>
<body>
  <div class="center">用内容撑开盒子</div>
</body>
</html>
复制代码

运行结果: 其实关键代码异常的简单,几乎没什么特别大的学习成本,就这么两行:

/* 令其变成网格布局 */
display: grid;

/* 令其子元素居中 */
place-items: center;
复制代码

Flex 弹性盒子

移动端布局王者 Flex :

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    /* 清除默认样式 */
    * { padding: 0; margin: 0; }

    /* 令html和body全屏显示, 并有一个灰色背景 */
    html, body { height: 100%; background: gray; }

    /* 找到中央盒子的直接父元素 */
    body {
      /* 令其变成弹性布局 */
      display: flex;
    }

    .center {
      /* 自动外边距 */
      margin: auto;

      /* 白色背景 */
      background: white;

      /* 不用给宽高,但是可以给个内边距防止内容与盒子过于贴合 */
      padding: 10px;
    }
  </style>
</head>
<body>
  <div class="center">用内容撑开盒子</div>
</body>
</html>
复制代码

运行结果: Flex 几乎没有不会的吧?超级好用,简单实惠又便捷,如果这个都不会的话可以去看看阮一峰老师的博客,里面有着很详细的入门教程:

另外,张鑫旭的博客写的也很不错:

表格布局

在居中布局这种场景下,表格布局也很适用:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    /* 清除默认样式 */
    * { padding: 0; margin: 0; }

    body {
      /* 令body全屏显示 */
      width: 100vw;
      height: 100vh;

      /* 显示为表格的格子 */
      display: table-cell;

      /* 水平居中 */
      text-align: center;

      /* 垂直居中 */
      vertical-align: middle;

      /* 灰色背景 */
      background: gray;
    }

    .center {
      /* 显示为行内块元素 */
      display: inline-block;

      /* 不用给宽高,但是可以给个内边距防止内容与盒子过于贴合 */
      padding: 10px;

      /* 白色背景 */
      background: white;
    }
  </style>
</head>
<body>
  <div class="center">用内容撑开盒子</div>
</body>
</html>
复制代码

运行结果: 此布局的关键点在于:

  • 父元素上 3 个样式设置:

    • display: table-cell;
    • text-align: center;
    • vertical-align: center;
  • 子元素上设置:

    • display: inline-block;

结语

看完这些有没有很郁闷,一个小小的居中布局都这么多种实现方式,而且这还不是全部的实现方式,我只挑了几款市面上常见的,可能大家会觉得有这个必要记这么多嘛!

其实这个问题就显得仁者见仁智者见智了,一方面面试造火箭,工作拧螺丝的现状让大家很苦恼。明明觉得自己技术还不错,至少公司要的都能给实现出来,但面试的时候面对面试官的刁难自己却无能为力。

也许下一次面试时并不会遇到一个面试官让你以各种方式实现居中布局,但开拓一下眼界总是好的,因为变换一下思路有助于大家在遇见复杂布局的时候可以快速选型。

该文章首发于前端学不动公众号

对了,这篇文章是连载形式的,居中布局仅仅只是一个开始,点赞 + 关注 我们下个布局见!

往期精彩文章

文章分类
前端
文章标签