前端面试实录CSS篇(最近一周)(下)

简介: 前端面试实录CSS篇(最近一周)(下)

18. z-index 会在什么情况下会失效?

  • • 作用及含义:设置元素的堆叠顺序,值越大就越在上层
  • • 检查以下情况:
  1. 1. 该元素是否设置了定位
  2. 2. 该元素的父级是否已经设置了z-index(检查需比较的元素是否同在一个层叠上下文)
  • • z-index 属性会在下列情况中会失效:
  1. 1. 在设置 z-index 的元素上必须含有 position 属性为非 static 属性值(relative,absolute,fixed)。
  2. 2. 同一个父级元素下的元素层叠效果是受父级影响的,就是说如果你的父级z-index很小,那你子级设置再大也没有用

19. 常见的 css 布局单位?

  • • 常用布局单位:像素px,百分比%,em,rem,vw/vh
  • • vmin: vw 和 vh 的较小值
  • • vmax: vw 和 vh 的较大值
  • • em:文本相对长度单位,浏览器默认的字体尺寸为 16px;
  • • rem: css3 新增的一个相对单位,是相对于根元素 html元素 的 font-size 的倍数,
  • • css 像素:web 开发者提供,css 中的一个抽象单位
  • • 物理像素:与设备的硬件密度相关,任何设备的物理像素都是固定的
  • • 像素px: 页面布局基础,分为css 像素和物理像素
  • • 百分比%: 实现响应式效果
  • • em和rem: 相对于 px 更具灵活性,它们都是相对长度单位,区别为,em 相对于父元素,rem相对于子元素
  • • vw/vh: 视图窗口单位,vw 宽度,vh 高度,还有 vmin 和 vmax 两个相关单位

20. px,em, rem 的区别以及使用场景?

  • • 区别:
  • • px: 固定像素,无法跟着页面大小而改变
  • • em: em 和 rem 相对长度单位,长度不是固定的,会跟着页面大小而改变,更适用于响应式布局
  • • em 相对于父元素来设置字体大小,而 rem 是相对于根元素来改变的
  • • 使用场景:
  • • 适配少部分的移动设备,且对分辨率对页面影响大小的可使用 px
  • • 适配各种移动设备,使用 rem

21. 两栏布局的实现

  • • 左边固定,右边自适应
  • • 利用浮动,将左边元素宽度设置为 200px,并且设置向左浮动。将右边元素的 margin-left 设置为 200px,宽度设置为 auto(默认为 auto,撑满整个父元素)。
.outer {
  height: 100px;
}
.left {
  float: left;
  width: 200px;
  background: tomato;
}
.right {
  margin-left: 200px;
  width: auto;
  background: gold;
}
  • • 利用浮动,左侧元素设置固定大小,并左浮动,右侧元素设置 overflow: hidden; 这样右边就触发了 BFC,BFC 的区域不会与浮动元素发生重叠,所以两侧就不会发生重叠。
.left{
     width: 100px;
     height: 200px;
     background: red;
     float: left;
 }
 .right{
     height: 300px;
     background: blue;
     overflow: hidden;
 }
  • • 利用 flex 布局,将左边元素设置为固定宽度 200px,将右边的元素设置为 flex:1。
.outer {
  display: flex;
  height: 100px;
}
.left {
  width: 200px;
  background: tomato;
}
.right {
  flex: 1;
  background: gold;
}
  • • 利用绝对定位,将父级元素设置为相对定位。左边元素设置为 absolute 定位,并且宽度设置为 200px。将右边元素的 margin-left 的值设置为 200px。
.outer {
  position: relative;
  height: 100px;
}
.left {
  position: absolute;
  width: 200px;
  height: 100px;
  background: tomato;
}
.right {
  margin-left: 200px;
  background: gold;
}
  • • 利用绝对定位,将父级元素设置为相对定位。左边元素宽度设置为 200px,右边元素设置为绝对定位,左边定位为 200px,其余方向定位为 0。
.outer {
  position: relative;
  height: 100px;
}
.left {
  width: 200px;
  background: tomato;
}
.right {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 200px;
  background: gold;
}

22. 三栏布局的实现

  • • 左右两遍固定。中间自适应
  • • 利用绝对定位,左右两栏设置为绝对定位,中间设置对应方向大小的 margin 的值。
.outer {
  position: relative;
  height: 100px;
}
.left {
  position: absolute;
  width: 100px;
  height: 100px;
  background: tomato;
}
.right {
  position: absolute;
  top: 0;
  right: 0;
  width: 200px;
  height: 100px;
  background: gold;
}
.center {
  margin-left: 100px;
  margin-right: 200px;
  height: 100px;
  background: lightgreen;
}
  • • 利用 flex 布局,左右两栏设置固定大小,中间一栏设置为 flex:1。
.outer {
  display: flex;
  height: 100px;
}
.left {
  width: 100px;
  background: tomato;
}
.right {
  width: 100px;
  background: gold;
}
.center {
  flex: 1;
  background: lightgreen;
}
  • • 利用浮动,左右两栏设置固定大小,并设置对应方向的浮动。中间一栏设置左右两个方向的 margin 值,注意这种方式,中间一栏必须放到最后:
.outer {
  height: 100px;
}
.left {
  float: left;
  width: 100px;
  height: 100px;
  background: tomato;
}
.right {
  float: right;
  width: 200px;
  height: 100px;
  background: gold;
}
.center {
  height: 100px;
  margin-left: 100px;
  margin-right: 200px;
  background: lightgreen;
}
  • • 圣杯布局,利用浮动和负边距来实现。父级元素设置左右的 padding,三列均设置向左浮动,中间一列放在最前面,宽度设置为父级元素的宽度,因此后面两列都被挤到了下一行,通过设置 margin 负值将其移动到上一行,再利用相对定位,定位到两边。
.outer {
  height: 100px;
  padding-left: 100px;
  padding-right: 200px;
}
.left {
  position: relative;
  left: -100px;
  float: left;
  margin-left: -100%;
  width: 100px;
  height: 100px;
  background: tomato;
}
.right {
  position: relative;
  left: 200px;
  float: right;
  margin-left: -200px;
  width: 200px;
  height: 100px;
  background: gold;
}
.center {
  float: left;
  width: 100%;
  height: 100px;
  background: lightgreen;
}
  • • 双飞翼布局,双飞翼布局相对于圣杯布局来说,左右位置的保留是通过中间列的 margin 值来实现的,而不是通过父元素的 padding 来实现的。本质上来说,也是通过浮动和外边距负值来实现的。
.outer {
  height: 100px;
}
.left {
  float: left;
  margin-left: -100%;
  width: 100px;
  height: 100px;
  background: tomato;
}
.right {
  float: left;
  margin-left: -200px;
  width: 200px;
  height: 100px;
  background: gold;
}
.wrapper {
  float: left;
  width: 100%;
  height: 100px;
  background: lightgreen;
}
.center {
  margin-left: 100px;
  margin-right: 200px;
  height: 100px;
}

23. 水平垂直居中的方式?

  1. 1. flex 布局
.parent {
    display: flex;
    justify-content:center;
    align-items:center;
}
  1. 1. 绝对定位 + margin
.parent {
    position: relative;
}
.child {
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top: -50px;     /* 自身 height 的一半 */
    margin-left: -50px;    /* 自身 width 的一半 */
}
  1. 1. 绝对定位
.parent {
    position: relative;
}
.child {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
}
  1. 1. 绝对定位 + transform
.parent {
    position: relative;
}
.child {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%,-50%);
}

24. 响应式设计的概念及基本原理?


  • • 响应式设计:也就是一个网站能兼容多个终端,而不是每个终端做一个适配
  • • 原理:通过媒体查询 @media 查询检测不同的设备屏幕尺寸做处理
  • • 关于兼容:页面头部必须要有 meta 声明的 viewport

25. position 的属性有哪些,区别是什么?

  • • absolute: 绝对定位的元素的位置相对于最近的已定位父元素,如果元素没有已定位的父元素,那么它的位置相对于
  • • relative: 相对定位元素的定位是相对其正常位置
  • • fixed: 元素的位置相对于浏览器窗口是固定位置。即使窗口是滚动的它也不会移动:
  • • static: HTML 元素的默认值,即没有定位,遵循正常的文档流对象。静态定位的元素不会受到 top, bottom, left, right影响。
  • • inherit: 规定从父元素继承 position 属性的
  • • sticky: 基于用户的滚动位置来定位
  • • 前面三者的定位方式如下:
  • relative:元素的定位永远是相对于元素自身位置的,和其他元素没关系,也不会影响其他元素。
    imgfixed:元素的定位是相对于 window (或者 iframe)边界的,和其他元素没有关系。但是它具有破坏性,会导致其他元素位置的变化。
  • 640.png

  • imgabsolute:元素的定位相对于前两者要复杂许多。如果为 absolute 设置了 top、left,浏览器会根据什么去确定它的纵向和横向的偏移量呢?答案是浏览器会递归查找该元素的所有父元素,如果找到一个设置了position:relative/absolute/fixed的元素,就以该元素为基准定位,如果没找到,就以浏览器边界定位。如下两个图所示:
    imgimg

26. absolute 与 fixed 的共同点与不同点?

  • • 共同点:
  • • 改变行内元素的呈现方式,将 display 改为 inline-block
  • • 使元素脱离普通文档流,不再占据文档物理空间
  • • 覆盖非定位文档元素
  • • 不同点:
  • • absolute 与 fixed 的根元素不同,absolute 的根元素可设置,fixed 的根元素是html
  • • 在有滚动的页面中,absolute 会跟随父元素进行滚动,而 fixed 固定在某个位置

27. 如何解决 1px 问题?

  • • 1px 问题的本质:在一些 Retina 屏幕上,移动端页面的 1px 会变得很粗,所呈现出来不止是 1px 的效果,原因就是 CSS 中的 1px 不能和移动端的 1px 划等号,他们之间是有一个比例关系。
window.devicePixelRatio = 设备的物理像素 / CSS像素。
  • • 解决方法:
  1. 1. 直接写 0.5px: 通过 js 拿到 window.devicePixelRatio 的值, 然后进行判断处理(如果是 1,则直接返回,否则 1 / window.devicePixelRatio),然后动态的设置 CSS 属性中的值,以此来达到 1px 的效果。
  • • 缺点:兼容性不行, andriod 直接不兼容,ios 需要 8.0 以上的版本
<div id="container" data-device={{window.devicePixelRatio}}></div>
  1. 1. 通过伪元素
#container[data-device="2"] {
    position: relative;
}
#container[data-device="2"]::after{
    position:absolute;
    top: 0;
    left: 0;
    width: 200%;
    height: 200%;
    content:"";
    transform: scale(0.5);
    transform-origin: left top;
    box-sizing: border-box;
    border: 1px solid #333;
}
  • • 缺点:代码较多,但兼容性好
  1. 1. viewport 缩放来解决
<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
  • • 这里针对像素比为 2 的页面,把整个页面缩放为了原来的 1/2 大小。这样,本来占用 2 个物理像素的 1px 样式,现在占用的就是标准的一个物理像素。根据像素比的不同,这个缩放比例可以被计算为不同的值,用 js 代码实现如下:
const scale = 1 / window.devicePixelRatio;
// 这里 metaEl 指的是 meta 标签对应的 Dom
metaEl.setAttribute('content', `width=device-width,user-scalable=no,initial-scale=${scale},maximum-scale=${scale},minimum-scale=${scale}`);
  • • 缺点:整个页面都会被缩放

28. 如何判断元素进入可视区域?

  1. 1. offsetTop、scrollTop
  2. 2. getBoundingClientRect
  3. 3. Intersection Observer
`window.innerHeight` 是浏览器可视区的高度;
`document.body.scrollTop || document.documentElement.scrollTop` 是浏览器滚动的过的距离;
`imgs.offsetTop` 是元素顶部距离文档顶部的高度(包括滚动条的距离);
内容达到显示区域的:`img.offsetTop < window.innerHeight + document.body.scrollTop;`
• • 方式一:offsetTop、scrollTop
// 公式
el.offsetTop - document.documentElement.scrollTop <= viewPortHeight
// 代码实现
function isInViewPortOfOne (el) {
    // viewPortHeight 兼容所有浏览器写法
    const viewPortHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
    const offsetTop = el.offsetTop
    const scrollTop = document.documentElement.scrollTop
    const top = offsetTop - scrollTop
    return top <= viewPortHeight
}
  • • 方式二:getBoundingClientRect
  • • 返回值是一个 DOMRect对象,拥有left, top, right, bottom, x, y, width, 和 height属性
const target = document.querySelector('.target');
const clientRect = target.getBoundingClientRect();
console.log(clientRect);
// {
//   bottom: 556.21875,
//   height: 393.59375,
//   left: 333,
//   right: 1017,
//   top: 162.625,
//   width: 684
// }
// A:
// 如果一个元素在视窗之内的话,那么它一定满足下面四个条件:
// top 大于等于 0
// left 大于等于 0
// bottom 小于等于视窗高度
// right 小于等于视窗宽度
// 代码实现
function isInViewPort(element) {
    const viewWidth = window.innerWidth || document.documentElement.clientWidth;
    const viewHeight = window.innerHeight || document.documentElement.clientHeight;
    const {
        top,
        right,
        bottom,
        left,
    } = element.getBoundingClientRect();
    return (
        top >= 0 &&
        left >= 0 &&
        right <= viewWidth &&
        bottom <= viewHeight
    );
}
  • • 方式三:Intersection Observer
  • • Intersection Observer 即重叠观察者,从这个命名就可以看出它用于判断两个元素是否重叠,因为不用进行事件的监听,性能方面相比getBoundingClientRect会好很多
  • • 使用步骤主要分为两步:创建观察者和传入被观察者
// 第一步:创建观察者
const options = {
    // 表示重叠面积占被观察者的比例,从 0 - 1 取值,
    // 1 表示完全被包含
    threshold: 1.0,
    root:document.querySelector('#scrollArea') // 必须是目标元素的父级元素
};
const callback = (entries, observer) => { ....}
const observer = new IntersectionObserver(callback, options);
// 通过new IntersectionObserver创建了观察者 observer,传入的参数 callback 在重叠比例超过 threshold 时会被执行`
// 上段代码中被省略的 callback
const callback = function(entries, observer) {
    entries.forEach(entry => {
        entry.time;               // 触发的时间
        entry.rootBounds;         // 根元素的位置矩形,这种情况下为视窗位置
        entry.boundingClientRect; // 被观察者的位置举行
        entry.intersectionRect;   // 重叠区域的位置矩形
        entry.intersectionRatio;  // 重叠区域占被观察者面积的比例(被观察者不是矩形时也按照矩形计算)
        entry.target;             // 被观察者
    });
};
// 第二步:传入被观察者
const target = document.querySelector('.target');
observer.observe(target);
  • • 实现代码:前两种方法
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js" integrity="sha512-STof4xm1wgkfm7heWqFJVn58Hm3EtS31XFaagaa8VMReCXAkQnJZ+jEy8PCC/iT18dFy95WcExNHFTqLyp72eQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <title>Document</title>
    <style>
        .container {
            display: flex;
            flex-wrap: wrap;
        }
        .target {
            margin: 5px;
            width: 20px;
            height: 20px;
            background: red;
        }
    </style>
</head>
<body>
    <div class="container"></div>
</body>
</html>
<script>
    (() => {
        const $container = $(".container");
        function createTargets() {
            const htmlString = new Array(10000).fill('<div class="target"></div>').join("")
            $container.html(htmlString)
        }
        createTargets();
        const $targets = $(".target");
        function isInViewPort(el){
            //方法1
            // const viewPortHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
            // const offsetTop = el.offsetTop;
            // const scollTop = document.documentElement.scrollTop;
            // return offsetTop-scollTop <= viewPortHeight
            // 方法2
            const viewPortHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
            const viewPortWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
            const {top,right,left,bottom} = el.getBoundingClientRect();
            return top >= 0 && left >= 0 && bottom <= viewPortHeight && right <= viewPortWidth
        }
        //事件监听
        $(window).on("scroll",()=>{
            console.log("scroll!!");
            $targets.each((index,element)=>{
                if(isInViewPort(element)){
                    $(element).css("background-color","blue")
                }
            })
        })
    })();
</script>
  • • 第三种方法
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js"
        integrity="sha512-STof4xm1wgkfm7heWqFJVn58Hm3EtS31XFaagaa8VMReCXAkQnJZ+jEy8PCC/iT18dFy95WcExNHFTqLyp72eQ=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .test {
            width: 200px;
            height: 1000px;
            background: orange;
        }
        .box {
            width: 150px;
            height: 150px;
            margin: 50px;
            background: red;
        }
        #sta {
            position: fixed;
            left: 40%;
            top: 40%;
            width: 200px;
            height: 100px;
            background: greenyellow;
        }
    </style>
</head>
<body>
    <div class="test">test</div>
    <div class="box">box</div>
    <div id="sta">初始化</div>
</body>
</html>
<script>
    (() => {
        var status_node=document.querySelector("#sta");
        const box = document.querySelector('.box');
        const intersectionObserver = new IntersectionObserver((entries) => {
            entries.forEach((item) => {
                if (item.isIntersecting) {
                    box.innerText = '进入可视区域';
                    status_node.innerText = '进入可视区域';
                    console.log('进入可视区域');
                }else{
                    box.innerText = '出去了';
                    status_node.innerText = '出去了';
                }
            })
        });
        intersectionObserver.observe(box);
    })();
</script>

特殊字符描述

问题标注 Q:(question)答案标注 R:(result)注意事项标准:A:(attention matters)详情描述标注:D:(detail info)总结标注:S:(summary)分析标注:Ana:(analysis)提示标注:T:(tips)

相关文章
|
11天前
|
Web App开发 前端开发 JavaScript
揭秘!前端大牛们如何巧妙利用CSS3,打造炫酷视觉效果!
【10月更文挑战第31天】前端开发面临复杂布局的挑战,本文介绍了几种提升开发效率和代码质量的工具和技术。基础的HTML和CSS可以应对大部分布局需求,而Firefox开发者工具、VS Code、Vue、React等则能应对更复杂的布局,帮助开发者构建高性能、用户友好的网页应用。
22 4
|
19天前
|
缓存 前端开发 JavaScript
"面试通关秘籍:深度解析浏览器面试必考问题,从重绘回流到事件委托,让你一举拿下前端 Offer!"
【10月更文挑战第23天】在前端开发面试中,浏览器相关知识是必考内容。本文总结了四个常见问题:浏览器渲染机制、重绘与回流、性能优化及事件委托。通过具体示例和对比分析,帮助求职者更好地理解和准备面试。掌握这些知识点,有助于提升面试表现和实际工作能力。
54 1
|
1月前
|
前端开发 JavaScript
CSS样式穿透技巧:利用scoped与deep实现前端组件样式隔离与穿透
CSS样式穿透技巧:利用scoped与deep实现前端组件样式隔离与穿透
152 1
|
1月前
|
前端开发 容器
前端技术分享:利用CSS Grid布局实现响应式设计
【10月更文挑战第1天】前端技术分享:利用CSS Grid布局实现响应式设计
|
1月前
|
前端开发 UED 容器
前端技术分享:利用 CSS Grid 实现响应式布局
【10月更文挑战第1天】前端技术分享:利用 CSS Grid 实现响应式布局
51 2
|
30天前
|
Web App开发 JavaScript 前端开发
前端Node.js面试题
前端Node.js面试题
|
1月前
|
前端开发 JavaScript 容器
前端之CSS基础知识
前端之CSS基础知识
16 0
|
1月前
|
前端开发 容器
【前端基础篇】CSS基础速通万字介绍(下篇)3
【前端基础篇】CSS基础速通万字介绍(下篇)
17 0
|
1月前
|
Web App开发 存储 前端开发
【前端基础篇】CSS基础速通万字介绍(下篇)2
【前端基础篇】CSS基础速通万字介绍(下篇)
18 0