HTML,CSS面试题

230 阅读7分钟

描述渐进增强和优雅降级之间的不同?

  • 渐进增强(progressive enhancement):针对低版本浏览器进行页面构建,保证最基本的功能,然后再针对高级浏览器进行效果,交互等改进。
  • 优雅降级(graceful degradation):一开始就构建完整的功能,然后再针对低版本浏览器进行兼容

image-20211005092151412.png

Quirks模式是什么?和standards模式有什么区别?

  • quirks怪异模式:在该模式下宽度和高度包含了padding和border,可以给行内元素设置宽高,设置margin 0 auto是不能生效的

link和@import有什么区别?

  • 从属关系的区别: @import是css提供的语法规则,只有导入样式表的作用;link是html提供的标签,不仅可以加载css文件,还可以定义RSS,rel连接属性等
  • 加载顺序的区别:加载页面时,link 标签引入的css被同时加载@import引入的css将在页面加载完毕后被加载
  • 兼容性得区别: @import是css2.1才有的语法,有浏览器的兼容性问题;link标签作为html元素没有兼容性问题
  • DOM可控性区别:可以通过js操作DOM,插入link标签来改变样式;无法使用 @import的方式插入样式
  • @import样式优先级没有link
  • 虽然link先加载,但是就在渲染时,由于 @import编写的位置是在靠前的位置,会被替换成css的样式,这个会被后面的link引入的样式层叠了,所以link的权重比@import高
  • @import添加的样式时在页面载入后再加载,这可能会导致页面因重新渲染而闪烁。所以建议使用link而不是@import

清除浮动

清除浮动是因为父元素没有设置高度,子元素浮动导致父元素高度塌陷
  • 在浮动元素后使用一个带clear属性的空元素

    • 优点:简单,代码少,浏览器兼容性好
    • 缺点:需要添加大量无语义的html元素,代码不够优雅,后期不易维护
  • 给父元素添加overflow:hidden或者auto

  • 给父元素after伪元素,给伪元素添加clear:both

src和href的区别?

  • src用于替换当前元素,而href用于建立这个标签与外部资源之间的关系
  • 当浏览器解析到href时,html的解析和渲染不会暂停,而解析到src页面的加载和解析都会暂停直到浏览器拿到并执行完。
  • 例如:a标签里面的内容是一张图片,a标签加上href将图片链接到了另一个网站,但并没有替换a标签里面的内容,而img标签的src属性则是将这个标签完全替换成了src里面的资源

减少dom数量的办法,一次性给大量的dom怎么优化?

减少dom数量的方法
  • 使用伪元素,阴影实现的内容尽量不使用DOM实现,如清除浮动。。。
  • 按需加载,减少不必要的渲染,类似于长列表的话可以只渲染可视区的DOM元素
  • document.getElementsByTagName('*').length可以获取到dom的数量
大量DOM时的优化
  • 文档片段

    • 利用document.createDocumentFragment()方法创建文档碎片节点,创建的是一个虚拟的节点对象。向这个节点添加dom节点,修改dom不会影响到真实的dom结构,可以利用这一点先将要修改的dom一次性改完,保存至文档碎片中,然后用文档碎片一次性替换真实的dom节点。这样就只会触发一次重排
    const app = document.getElementById("app");
    let fragment = document.createDocumentFragment();
    const li = document.createElement("li");
    li.innerHTML = "li";
    for (let i = 0; i < 10000; i++) {
        const test = li.cloneNode(true);
        fragment.appendChild(test);
    }
    app.appendChild(fragment);
  • 在操作大量dom时,可以先将父元素设置display:none,然后在对父元素进行操作,最后再将父元素display:block这样只会在一开始和最后触发重排
  • 采用requestAnimationFrame(cb),让浏览器在下次重绘之前执行cb函数
  • 虚拟dom

js获取样式?

  • 通过div.style.width只能获取到行内设置的样式,如果不是行内的样式就获取不到
  • 通过getComputedStyle(el)可以获取到元素的所有样式

SEO优化

  • 控制首页链接数量
  • 扁平化的目录层次:尽量跳转3次就能到达网站的任何一个内页
  • 导航尽量采用文字方式,也可以搭配图片导航,但是img标签必须添加alt title属性,做到即使图片未能正常显示,用户也能看到提示文字
  • 把重要内容HTML代码放到最前面,搜索引擎抓取是从上往下,利用这一特点可以让主要代码优先读取
  • 控制页面大小,减少http请求,提高网站加载速度。
  • 合理设置title <meta description> <meta keywords>
  • 采用语义化标签
  • 正文标题用h1标签
  • 重要内容不要用js,必须放在HTML中,“蜘蛛”是不会读取js里的内容

伪类和伪元素的区别

  • 伪类核心就是用来选择DOM树之外的信息,不能被普通选择器选择的文档之外的元素,用来添加一些选择器的特殊效果,如::hover:active :link visited
  • 伪元素核心就是创建不存在于文档中的元素,例如:::after ::before

css选择器

  • 通配符选择器 * {}
  • 标签名选择器 div {}
  • 类选择器 .test {}
  • id选择器 #test {}
  • 相邻选择器 test + test2 {}
  • 子选择器 test > test1 {}
  • 后代选择器 test test2 {}
  • 属性选择器 a[name = ''] {}
  • 伪类选择器 a:hover {}

实现div宽度自适应,宽高保持等比缩放

  • 直接使用宽高来实现
.demo {
    width: 30%;
    height: 30vh;  /* 这里高度不能用百分比,因为默认高度是0 */
    background: red;
}
  • 使用padding来实现

    • 由于margin和padding的百分比数值是相对于父元素的宽度计算的
.demo {
    width: 30%;
    height: 0;    /* 这里设置高度为0是为了防止内容高度影响 */
    padding-bottom: 30%;  /* 这样设置后max-height就失效了 */
    background: red;
}
  • 使用伪元素的margin(padding)-top(bottom)
.demo {
    width: 30%;
    overflow: hidden;  /* 如果采用margin就需要,因为margin会有外边距重合,采用padding就不需要 */
    background: red;
}
.demo::after {
    content: '';
    display: 'block';
    margin-top: 30%;  
}
/* 这样写法父元素的max-height属性不会失效 */

content-box和border-box的区别

  • content-box:width/height = border + padding + content width/height
  • border-box: width = content width

为什么居中要使用transform而不是用margin?

  • transform是独立的层,而margin会引起重绘和回流
transform的原理

transform是通过创建一个renderLayers合成层,拥有独立的graphicsLayers绘图层。每一个绘图层都会有一个绘图上下文,其对应的renderLayers合成层会被paint绘制到绘图上下文中。合成器compositor最终会负责将绘图上下文输出的位图合并成最终屏幕展示的图案。

image-20211005174502664.png 如果renderLayer是一个独立的合成层,那么它有属于自己的绘图层GraphicsLayer,否则就会和它最近的拥有GraphicsLayer绘图层的父层共用一个绘图层。

transform发生在composite Layer这一步,它所引起的paint也只是发生在单独的绘图层中,并不会引起整个页面的回流重绘。

transform实际上用到了GPU加速,也就是说占用了内存。由此可见创建绘图层,虽然节省了layout,paint阶段,但是layer创建的越多,占用的内存越大,过多的渲染开销会超过性能的改善。

flex:1完整的写法是什么?分别是什么意思?

  • flex:1的完整写法是
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0%;
  • flex-grow定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大
  • flex-shrink定义了项目的缩小比例,默认为1,即如果空间不足,将该项目缩小
  • flex-basis给上面两个属性分配多余空间之前,计算项目是否有多余空间,默认值为auto,即项目本身的大小
  • flex:none
flex-grow: 0;
flex-shrink: 0;
flex-basis: auto;
  • flex:auto
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;

css实现动画的方式

  • hover
  • transition
  • animation

nth-childnth-type-of的区别

  • nth-child(n): 先根据后面的数字选中父元素的第n个元素,在判断这个子元素是否是前面的选择器,如果是,则样式生效,否则样式不生效
  • nth-of-type(n): 先在父元素中找出所有符合起前面选择器的子元素,再从这些子元素中选择第n个元素

用css画三角形

/* 正三角 */
.triangle {
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 0 25px 40px 25px;
    border-color: transparent transparent red transparent;
}
/* 倒三角 */
.triangle {
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 40px 25px 0 25px;
    border-color: red transparent transparent transparent;
}

css实现单行省略号

.single-ellipsis {
    width: 400px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

inherit,initial,unset三者的区别

  • initial:简单的说就是初始化到该属性浏览器默认定义的值
  • inherit:可以通过inherit将默认不会继承的属性继承过来
  • unset:可以简单理解为不设置,其实它是initial和inherit的组合,如果属性默认可以继承,那么就是inherit,如果默认不继承,那么就是initial

用css实现一个扇形

.sector {
    width: 200px;
    height: 200px;
    border-radius: 200px 0 0 0;
    background: red;
}