Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS Viewport 单位,很多人还不知道使用它来快速布局! #243

Open
husky-dot opened this issue Jul 1, 2020 · 0 comments
Open

Comments

@husky-dot
Copy link
Owner

作者:Ahmad shaded
译者:前端小智
来源:sitepoint

点赞再看,养成习惯

本文 GitHub https://github.com/qq449245884/xiaozhi 上已经收录,更多往期高赞文章的分类,也整理了很多我的文档,和教程资料。欢迎Star和完善,大家面试可以参照考点复习,希望我们一起有点东西。

**CSS Viewport units(视口单位)**在过去几年已经出现了,随着时间的推移,越来越多的开发人员开始使用它们。它们的好处在于为我们提供了一种不需要使用J avaScript 就能以动态的方式调整大小的方法。而且,如果它失效,也有很多备用方案。

在本文中,我们将学习 CSS Viewport units(视口单位)以及如何使用它们,并用列举一些常见问题及其解决方案和用例,让我们开始吧。

简介

根据CSS规范,视口百分比单位相对于初始包含块的大小,它是web页面的根元素。

视口单位为:vwvhvminvmax

vw单位表示根元素宽度的百分比。1vw等于视口宽度的1%

视口宽度

vw单位表示根元素宽度的百分比,1vw等于视口宽度的1%

假设我们有一个元素与以下CSS:

.element {
    width: 50vw;
}

当视口宽度为500px时,50vw计算如下

width = 500*50% = 250px

视口高度

vh单位表示根元素高度的百分比,一个vh等于视口高度的1%

我们有一个元素与以下CSS:

.element {
    height: 50vh;
}

当视口高度为290px时,70vh计算如下:

height = 290*70% = 202px

大家都说简历没项目写,我就帮大家找了一个项目,还附赠【搭建教程】

Vmin 单位

vmin表示视口的宽度和高度中的较小值,也就是vwvh 中的较小值。如果视口宽度大于其高度,则将根据高度计算该值。

我们以下面的例子为例。

我们有一个横屏手机,其中有一个元素具有vmin单元。在这种情况下,值将根据视口高度计算,因为它小于宽度。

.element {
    padding-top: 10vmin;
    padding-bottom: 10vmin;
}

这是vmin的计算方式:

正如你所猜测的,计算结果如下所示

padding-top = (10% of height) = 10% * 164 = 16.4px 

padding-bottom = (10% of height) = 10% * 164 = 16.4px

Vmax 单位

vmaxvmin相反,该值是vwvh 中的较大值。

我们以下面的例子为例。

.element {
    padding-top: 10vmax;
    padding-bottom: 10vmax;
}

计算结果如下:

padding-top = (10% of width) = 10% * 350 = 35px 
padding-bottom = (10% of width) = 10% * 350 = 35px

视口单位与百分比有何不同?

视口单位基于页面的根元素,而百分比则基于它们所在的容器。因此,它们彼此不同,但各自都有各自的用处。

视口单位的用例

字体大小

CSS 视口单位非常适合响应式排版。 例如,我们可以将以下内容用作文章标题:

.title {
    font-size: 5vw;
}

标题的font-size将根据视口宽度增加或缩小。 就像提供的字体大小是视口宽度的5%一样。 但是,如果没有适当的测试就直接使用它可能会踩到坑。 让我们看下面的视频:

体大小变得非常小,这不利于可访问性和用户体验。据我所知,移动设备上的最小字体大小不应该不于14px。在GIF中,不小于10px

要解决该问题,我们需要为标题提供最小字体大小,可以使用 calc()

.title {
    font-size: calc(14px + 2vw);
}

calc()CSS函数将具有一个最小值14px,并在些基础上添加2vw的值,有了这些,字体大小值就不会变得太小。

另一个需要考虑的重要问题是字体大小在大屏幕上的表现,例如 27” iMac。会发生什么呢?你猜对了,字体大小为95px左右,这是一个很大的值。为了防止这种情况,我们应该在某些断点上使用媒体查询并更改字体大小。

@media (min-width: 1800px) {
    .title {
        font-size: 40px;
    }
}

通过重置字体大小,我们可以确保大小不会太大。您可能还需要添加多个媒体查询,但这取决于你自己,也取决于项目的上下文。

事例地址:https://codepen.io/shadeed/pen/fa989837c6379770cce49f0be6daa3e3

全屏

有时,我们需要一个section来获取100%的视口高度,为此,我们可以使用viewport高度单位。

.section {
    height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}

通过添加 height: 100vh,我们可以确保section 高度将采取100%的视口。此外,我们添加了一些flexbox来处理水平和垂直居中的内容。

事例源码:https://codepen.io/shadeed/pen/dc4e82f3c873cc64ae5c5bc4a3f4ef9f?editors=1100

粘性布局(footer)

在大屏幕上,网站内容有时候很少,footer 没有粘在底部。这很正常,也不被认为是一种不好的做法。但是,还有改进的余地。考虑下面代表问题的示图:

为了解决这个问题,我们需要给内容(content)一个高度,它等于视口高度- (header + footer)。动态地做到这一点是很困难的,但是使用CSS的视口,这是很容易的。

大家都说简历没项目写,我就帮大家找了一个项目,还附赠【搭建教程】

第一种解决方案:calc和视口单位

如果headerfooter 的高度是固定的,那么可以将calc()函数和视口单位结合起来,如下所示:

header,
footer {
    height: 70px;
}

main {
    height: calc(100vh - 70px - 70px);
}

不能保证此解决方案始终有效,尤其是对于footer而言。 在我的职业生涯中,我没有使用固定高度的页脚,因为在例如不同的屏幕尺寸下,此footer是不可行的。

2.第二种解决方案:Flexbox和视口单位(推荐

通过将100vh设置为body元素的高度,然后可以使用flexbox来使main元素占用剩余空间。

body {
    min-height: 100vh;
    display: flex
    flex-direction: column;
{

main {
    /* This will make the main element take the remaining space dynamically */
    flex-grow: 1;
}

这样,问题就解决了,无论内容长度如何,我们都有一个粘性footer

事例源码:https://codepen.io/shadeed/pen/c735b26b8fa97ee685b38084448b3f85?editors=1100

响应式元素

假设我们有一个作品集来展示我们的响应式设计工作,并且我们有三种设备(移动设备、平板电脑和笔记本电脑)。每个设备包含一个图像。目标使用 CSS 来响应适配这些页面。

通过使用CSS网格和视口单位,我们可以使其完全动态的响应式。

<div class="wrapper">
  <div class="device laptop"></div>
  <div class="device mobile"></div>
  <div class="device tablet"></div>
</div>

视口单位也可以用于grid- *属性,也用于borderborder-radius和其他属性。

.wrapper {
  display: grid;
  grid-template-columns: repeat(20, 5vw); 
  grid-auto-rows: 6vw;
}

.mobile { 
  position: relative;
  z-index: 1;
  grid-column: 2 / span 3;
  grid-row: 3 / span 5;
}
 
.tablet {
  position: relative;
  z-index: 1;
  grid-column: 13 / span 7; 
  grid-row: 4 / span 4;
  border-bottom: 1vw solid #a9B9dd;
  border-right: solid 3vw #a9B9dd;
}
 
.laptop {
  position: relative;
  grid-column: 3/span 13;
  grid-row: 2 / span 8;
}

/* Viewport units are used for the bottom, left, right, height, and border-radius. Isn't that cool? */
.laptop:after {
    content:"";
    position:absolute;
    bottom: -3vw;
    left: -5.5vw;
    right: -5.5vw;
    height: 3vw;
    background-color: #a9B9dd;
    border-radius: 0 0 1vw 1vw;
}

例:https://codepen.io/shadeed/pen/2da0f2b70699769f8de3220ff4465bc6?editors=1100

从容器中挣脱出来

我注意到一个用例最适合编辑版面。 一个子元素,即使父元素的宽度受到限制,它也会占据视口100%的宽度。 考虑下面:

.break-out {
    width: 100vw;
    position: relative;
    left: 50%;
    right: 50%;
    margin-left: -50vw;
    margin-right: -50vw;
}

让我们把它分解一下,这样我们就能一点一点地理解所有这些属性是如何工作的。

1.添加 width: 100vw

最重要的一步,将图像的宽度设置为100%的视口。

2.添加 margin-left: -50vw

为了使图像居中,我们需要给它一个负的边距,其宽度为视口宽度的一半。

3.添加 left: 50%

最后,我们需要将图像向右推,其值为父宽度的50%

事例地址:https://codepen.io/shadeed/pen/828f12b1ef7fa7211584ff5c7b82d2fa?editors=1100

垂直和水平间距

我想到的另一个有趣的用例是使用视口单位来表示元素之间的间距。这可以与margintopbottomgrid-gap等值一起使用。使用时,间距将基于视口宽度或高度,这对于使布局更具动态性可能很有用。

模态框

对于模态,我们需要将它们从视口顶部推入。 通常,使用top属性进行此操作,并使用百分比或像素值。 但是,对于视口单位,我们可以添加一个可以根据视口高度改变的间距。

.modal-body {
    top: 20vh;
}

事例地址:https://codepen.io/shadeed/pen/f77a0d58947c64c2b3dadbd887700db5?editors=1100

大家都说简历没项目写,我就帮大家找了一个项目,还附赠【搭建教程】

页面头部

页面header 是充当页面介绍的部分。 它通常具有标题和描述,并且其中上下边缘的高度固定或填充

例如,有以下的CSS的样式:

.page-header {
    padding-top: 10vh;
    padding-bottom: 10vh;
}

.page-header h2 {
    margin-bottom: 1.5vh;
}

使用vh单位用于页面标题的 paddding,以及标题下方的边距。 注意间距如何变化!

事例源码:https://codepen.io/shadeed/pen/43024fa031519e316e95bb3ce47f2b22?editors=1100

Vmin 和 Vmax 用例

该用例是关于页面标题元素的顶部和底部padding 。 当视口较小(移动)时,通常会减少padding 。 通过使用vmin,我们可以在视口较小尺寸(宽度或高度)的基础上获得合适的顶部和底部 padding

.page-header {
    padding: 10vmin 1rem;
}

事例源码:https://codepen.io/shadeed/pen/f335c2f43b960a2c70ea057228ddc5b9?editors=0100

纵横比

我们可以使用vw单位创建响应元素,以保持其纵横比,而不管视口大小如何。

首先,需要先确定所需的纵横比,对于此示例,使用9/16

section {
    /* 9/16 * 100 */
    height: 56.25vw;
}

事例源码:https://codepen.io/shadeed/pen/dc4e82f3c873cc64ae5c5bc4a3f4ef9f?editors=0100

流行的顶部边框

你知道大多数网站使用的顶部边框吗? 通常,它的颜色与品牌颜色相同,这会赋予一些个性。

我们支持边框的初始值为3px。 如何将固定值转换为视口对象?下面是如何计算它的等效的vw

vw = (Pixel Value / Viewport width) * 100

视口宽度用于估计像素值与所需vw单位之间的比率。

对于我们的示例,我们为 header 添加以下样式:

.header {
    border-top: 4px solid #8f7ebc;  
}

在我的情况下,视口宽度为1440(这不是固定数字,请用你自己的数字替换)

vw = (4 / 1440) * 100 = 0.277
.header {
    border-top: 0.277vw solid #8f7ebc;  
}

更好的是,我们可以使用一个基本像素值,而视口单元可以是一个附加的。

.header {
    border-top: calc(2px + 0.138vw) solid $color-main;
}

移动端滚动问题

移动设备中存在一个常见问题,即使使用100vh,也会滚动,原因是地址栏的高度可见。Louis Hoebregts 写了一篇关于这个问题的文章,并给出了一个简单的解决方案。

.my-element {
  height: 100vh; /* 不支持自定义属性的浏览器的回退 */
  height: calc(var(--vh, 1vh) * 100);
}
// 首先,我们得到视口高度,我们乘以 1% 得到一个vh单位的值
let vh = window.innerHeight * 0.01;
// 然后,将`--vh`自定义属性中的值设置为文档的根目录一个属性
document.documentElement.style.setProperty('--vh', `${vh}px`);

事例源码:https://codepen.io/shadeed/pen/1d18ca2d23ec0038c759dc62dc3fd8c3?editors=0110


代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug

原文:https://ishadeed.com/viewport-units/


交流

文章每周持续更新,可以微信搜索「 大迁世界 」第一时间阅读和催更(比博客早一到两篇哟),本文 GitHub https://github.com/qq449245884/xiaozhi 已经收录,整理了很多我的文档,欢迎Star和完善,大家面试可以参照考点复习,另外关注公众号,后台回复福利,即可看到福利,你懂的。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant