关于绝对定位和overflow的可见与不可见

之前给首页做周年主题皮肤时遇到一个问题,写了个demo,然后又遇到了问题

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .main {
            width: 1200px;
            height: 900px;
            margin: auto;
            position: relative;
        }

        .main-banner {
            width: 1200px;
            height: 100%;
            background: pink;
        }

        .banner-plugins {
            position: absolute;
            top: 0;
        }

        .banner-bg-left {
            left: -311px;
        }

        .banner-bg-right {
            right: -293px;
        }
    </style>
</head>
<body>
    <div class="main">
        <img src="./banner-bg-left.png" class="banner-plugins banner-bg-left">
        <img src="./banner-bg-right.png" class="banner-plugins banner-bg-right">
        <div class="main-banner"></div>
    </div>
</body>
</html>
复制代码

效果就是这个样子的

但是这样有个问题,当viewport宽度小于内容宽度,就会出现横向滚动条↓

这就很影响用户体验了,也不是我们想要的效果,我们想要的效果应该是,当宽度不足时,应该裁剪两侧图片的宽度来填充内容宽度。这个地方就涉及到一个知识点,为什么会出现滚动条?

W3C标准中指明: 通常一个盒子的内容是被限制在盒子边界之内的。但有时也会产生溢出,即部分或全部内容跑到盒子边界之外。溢出将在满足下列条件之一时出现:

  1. 一个不换行的行元素宽度超出了容器盒子宽度。
  2. 一个宽度固定的块元素放在了比它窄的容器盒子内。
  3. 一个元素的高度超出了容器盒子的高度。
  4. 一个子孙元素,由负边距值引起的部分内容在盒子外部。
  5. text-indent属性引起的行内元素在盒子的左右边界外。
  6. 一个绝对定位的子孙元素,部分内容在盒子外。但超出的部分不是总会被剪裁。子孙元素的内容就不会被子孙元素和其包含块之间的祖先元素的overflow的设置所剪裁。

我们遇到的就是第6条了,感觉很拗口,大概意思总结一下就是,假如我来自火星,秀恩爱不犯法,来地球后有规则秀恩爱犯法,但是诶,管不着我。就是这个意思。(涉及知识点包含块)

问题产生的原因找到了,那么就能找到解决方案了,目的是为了当内容部分超出可视区域的时候,隐藏它!

很自然地就想到在body上加一个overflow-x: hidden。自然,确实是达到效果了,但是,中间的主体部分假如是1200px,希望的是如果可视区域小于1200px就会出现横向滚动条,但是在body上加了这个之后就不能实现这个效果了。那能怎么办呢?最好的办法是换成背景图片就好了。

以上,就是这次换肤踩的坑,听说duety也踩了,分享一下。

唔,我在写demo的时候遇到一个问题,还是刚开始的代码,当可视区域宽度小于内容宽度的时候,出现横向滚动条,这时候就会发现一个问题,当我缩小可视区域宽度到出现滚动条的时候,会发现,左边的图片会被切割,但是右边的图片由于溢出了,拉动滚动条就能看到全部的图片,为什么左边会被切割呢?

我调整可视区域的宽度到刚好1200的时候,发现body的内容+溢出正好等于粉色部分+右边图片的宽度

我想了很久,我个人猜测:因为绝对定位脱离了文档流。

唔,怎么理解呢。文档流就是在元素排版布局的时候,元素会自动从左往右,从上到下进行排列,这时候没有css也是依照这个顺序排列的。但是呢,脱离文档流就不一样了,脱离了文档流之后,它的位置就跟文档写的顺序不一定一致了,并且原本在正常文档流中所占的空间也没有了。

结合上面的图来进行理解,我是这样想的:

元素排版布局的时候,因为可视区域的宽度正好等于文档流中的粉色部分的宽度,并且绝对定位左边的那一部分的空间是没有了的,所以粉色部分排列出来是紧挨着浏览器边缘的,再看绝对定位的脱离文档流的部分,左边这一块被css推到了左边,但是可视区域正好只能允许看到粉色部分,粉色部分已经紧贴边缘了,滚动条也是紧贴着左边的,即便出现了滚动条,也不能再往左划对不对,于是左边的就被不可见了,但是它的dom结构依然是存在的,等于说,虽然我们看不见左侧部分,但是它依然与我们同在;

浏览器继续渲染,到绝对定位右边这一块的时候,因为宽度不允许我们依然看不到它,但是呢,因为溢出,出现了滚动条,所以滑动滚动条将它滑至可视区域就可见。

如果可视区域稍大一点,粉色部分的宽度+一点,再看看是什么效果

还是按照上面的说法,从左往右渲染的时候,粉色部分排在绰绰有余的可视区域内,当渲染绝对定位的元素的时候,可视区域除开正常文档流宽度1291-1200=91,还剩91px的宽度,这点宽度留给脱离文档流的元素进行平分可视区域,所以左边这部分在css的作用下占据了粉色部分左边的位置,可见的宽度是46px(为啥不是45.5,那就是另外的事了),同理,右边也是只能看到那一点,由于溢出,所以出现滚动条,滑动就可见。

我个人的猜想是这样的。可以讨论一下,以上。

=======================================

给这个问题找原因的时候,发现了一个属性direction: ltr;,很少用,但是可以了解一下,还有很类似的近亲writing-mode: vertical-rl;,这个是针对文本的对齐方式,应该比上面的要更容易想到怎么用一点,也可以了解一下

猜你喜欢

转载自juejin.im/post/5c64ff216fb9a049fd105ae6
0条评论
添加一条新回复