某著名小白说过 :世上本来到处都是坑,只要走的人多了,也就把坑都给埋了。该小白还说过:坑本身并不可怕,可怕的是踩了一次之后,还第二、第三次踩到了相同的坑。

所谓"坑",主要是由于我们对某些知识点理解不够透彻,导致在应用的时出现了一些奇怪的问题。因为我们每个人,对于某个知识点的理解程度不一样,所以,有些坑我觉得真的很坑,但是你可能觉得一点都不坑,因为你早就对它了如指掌了。

这里列举的一些坑,都是我过去一年在项目中所遇到过的,并当时在笔记中记录下来的,现在稍加整理就形成了这篇博客,以供日后查阅。

不知不觉,开头又bb了这么多,还是赶紧进入正题哈。

1. 设置透明度(opacity)引起的惨案

之前做炉石盒子的天梯环境页面,地址是 炉石天梯环境 ,就在项目做得差不多的时候,准备上线了, QA 突然发现了如下的一个 bug:

有一个选择排序方式的下拉菜单,它的定位是 position: absolute,正常来说,它应该会覆盖在其他元素之上的,可是为什么 0.14% 反而会覆盖在它上面呢? 在代码中找了好久,那个 0.14% 并没有设置 z-index属性,也没有 position: absolute 这样的东西,真是好郁闷哦。后来到 mdn 查文档才发现,原来是 opacity属性引起 的: opacity 属性值小于 1 的元素会创建新的层叠上下文 。因为当时我有个偷懒的做法,字体继承的颜色是 #666, 我想让 0.14% (天梯比率)颜色变浅一些,直接加了个 opacity: 0.6 ,导致了创建了新的层叠上下文,层级比下拉菜单高了,所以就覆盖在了上面。具体什么是层叠上下文,以及哪些属性会创建新的层叠上下文,这里也不介绍了有需要的可以参考一下 层叠上下文

虽然上面描述得已经很详细了,但是可能由于我的表达能力不太好,有些朋友还不是很明白我的意思,可以看一下这里的 demo 代码:

<div class="menu"><div class="title">下拉菜单</div><div class="menu-list"><div class="item">菜单1</div><div class="item">菜单2</div><div class="item">菜单3</div></div>
</div>
<div class="content">我是半透明的文字,可以覆盖在下拉菜单之上哦~
</div>
<style>.menu {position: relative;}.menu-list {display: none;position: absolute;background: #ccc;}.menu:hover .menu-list {display: block;}.content {opacity: 0.6;}
</style>
复制代码

将鼠标移动到下拉菜单上,就会发现文字会发生重叠了:

那这个坑有什么解决办法呢?最简单的就是下拉菜单添加个属性 z-index: 1 。另外,这里再啰嗦一下,就是z-index的值不要乱设置。以前刚刚接触前端时,会经常看一些视频教程,看到里面讲师动不动就设置个 z-index: 999 之类的特别大的数值。这是一个不好的习惯。张鑫旭老师在《CSS世界》一书中,提到了 不三原则,就是说一般情况下,z-index的值不要超过3,基本能满足大多数的需求了。

2. flex布局:子项溢出后无法查看全部内容

之前做漫画阅读器,因为漫画可能有长图片,也可能有短图片。长图片可以滚动查看,短图片就居中显示。所以,很自然会想到用 flex 布局来实现。简单的代码如下:

<div class="app"><img src="https://m.tuniucdn.com/fb2/t1/G1/M00/F1/51/Cii9EFkAaZ-IRgGNAATB18ldk0UAAJzuQN-p1cABMHv15.jpeg" alt="">
</div>
<style>html,body {height: 100%;}.app {display: flex;height: 100%;justify-content: center;align-items: center;}img {width: 100%;}
</style>
复制代码

这里,我们的 .app 容器里面这里有一张很长的图片。当我们运行上面的代码,如果你仔细观察原图和页面显示的图片,就会发现图片的顶部和底部的一些内容看不到了,滚动条到了一定位置就无法滚动了。正常来说,我们应该可以通过滚动条的上下滑动看到图片的全部内容才对的。当时我想了很久也没有想出来原因,最后到 stackoverflow 找到了答案 Can't scroll to top of flex item that is overflowing container

答案中有提到,可以设置子项的 margin: auto 来实现内容溢出时也自动居中(包括水平和垂直的):

修改后的 CSS 代码如下:

  .app {display: flex;height: 100%;}img {width: 100%;margin: auto;}
复制代码

所以,以后如果在使用 flex 布局实现居中,如果子项的内容会溢出 flex 容器 ,可以将子项设置为 margin: auto 试试。

3. transfrom 和 fixed 不能在一起!

CSS3 的 transform 属性也算是比较常用的,特别是做一些动画效果的时候,用它来移动元素的位置,性能会比设置 top 或 left 要高一些。但是,如果一个元素设置了 transform 属性,而它的子元素又设置 fixed 定位,那么这个 fixed 定位的子元素表现会有些奇怪,如下代码:

<div class="app"><button onclick="layer.style.display='block'">弹出蒙层</button><div class="layer" id="layer"></div>
</div><style>.app {position: relative;width: 100px;height: 100px;background: #ccc;/* 使用transform让元素向下偏移20px */transform: translate(0, 20px);}.layer {display: none;position: fixed;top: 0;right: 0;bottom: 0;left: 0;background: rgba(0, 0, 0, 0.7);}
</style>
复制代码

打开页面,效果是这样的:

我们希望点击“弹出蒙层”按钮后,就显示个覆盖整个窗口的蒙层。但是结果却出乎意料。如下:

蒙层只是遮住了小正方形,这不是我们想要的结果,因为我们知道,fixed 定位是相对于屏幕视口(viewport)定位的, 但是,本例却相对于它的父亲元素。这是为什么呢?如果认真查阅 mdn文档 ,就会找到答案:

可见,问题的原因在于,我们只是记住了fixed是相对于 viewport 定位,但是也有特殊情况: 当元素祖先的 transform 属性非 none 时,容器由视口改为该祖先 。所以,这并不是bug,是因为我基础不扎实导致的。事实上, 除了 transform 会改变 fixed 的定位元素之外,还有其他属性也会改变,ChokCoco大佬有一篇文章做了详细的讲解,想要了解更多的请点击 不受控制的 position:fixed

那遇到这种情况怎么办呢?比较好的办法就是把 fixed 元素移到外面去,不要放到有 transform 属性的元素里面。但是,有时候我们没有办法移到外面怎么办呢?比如,这是它是一个子组件,它的某个父亲组件就是用了 transform,那怎么办呢?我也不知道怎么办,欢迎大家探讨一下哈哈哈~

fixed 定位还具有其他的坑,这里也不展开了,有兴趣的可看 看github 上有大佬整理好的这篇文章 移动端web页面使用position:fixed问题总结

4. 安卓微信视频播放器的层级问题

我们都知道, video 标签设置了 playsinline 就可以内联播放视频,而不是全屏播放。(注意:前提是客户端的 Webview 配置了允许内联播放,所以有时候虽然设置了 playsinline,但在某些 app 里面打开依然是全屏播放,这不是前端的锅哦)。最近有一个需求,类似下面这样的:

页面上有一个视频,视频播下面有一个按钮,点击按钮就弹出一个图片,该图片要覆盖整个屏幕,比如是这样的:

示例代码如下:

<video id="video" controls="" playsinline="" src="https://vod.cc.163.com/file/5bcbe1ae9efdc0608bb6d06b.mp4"></video>
<img id="image" src="https://ds.163.com/2018/mrzh/appointment/static/img/bg-body.cdef1ec.jpg" alt="">
<button id="button">弹出图片</button>
<style>video,img {width: 100%;}img {display: none;position: absolute;top: 0;}
</style><script>var video = document.getElementById('video');var image = document.getElementById('image');var button = document.getElementById('button');button.onclick = function() {image.style.display='block';}image.onclick = function() {this.style.display='none';}
</script>
复制代码

但是,在安卓上却发现一个问题,开始播放视频后(注意,只有播放视频后才可以复现),点击“弹出图片”按钮,显示如下所示:

图片无法覆盖在视频播放器上面。然后,我设置了 z-index 或者 transform ,都没有任何效果。最后, 剩下的可能原因就是: 安卓微信视频播放器实际上用的是原生组件。为了验证这一猜想,我们可以启用开发者选项的绘图模式 (开发者选项 --> 绘图 --> 显示布局边界,不同机型不一样,找不到的请百度找一下哈),结果如下:看到没有,视频是一个完整的有边框的东西,证明他是一个独立于 Webview 的原生组件。

那怎么办呢?只能上网找答案呀!我们都知道,微信 webview 使用的是 X5 内核,所以我也希望能从它的开发者文档上找到一些有用的信息,好不容易找到了一篇叫做 H5同层播放器接入规范 。它说可以可以在 video 标签添加一个属性 x5-video-player-type ,并且给出的例子是这样的:

<video src="http://xxx.mp4" x5-video-player-type="h5"/>
复制代码

我当时很高兴,以为问题就这样解决了,然并卵,添加了 x5-video-layer-type 属性之后,playsinlie 属性就失效了,无法内联播放了,只能全屏播放,所以,不能添加这个属性。

然后我就想,既然无法覆盖这个视频,那在弹出图片的时候能不能把视频给隐藏掉?然后关闭图片的时候再把视频显示回来呢?于是就把 JS 代码改成下面这样:

  button.onclick = function() {image.style.display='block';video.style.display = 'none';}image.onclick = function() {this.style.display='none';video.style.display = 'block';}
复制代码

然后,这样就可以了。因为我在网上找不到更好的办法,如果大家遇到这个问题可以参考这种做法。当然,如果你们找到了有更好的办法,欢迎评论分享出来哈~

关于安卓微信视频播放器的坑就先讲到这里啦。

等等,一讲到原生组件,这里还得再补充一下微信小程序相关的东西,当然,我自己还没有过小程序的开发的经验, 这是之前的一次内部交流会,一位同事的分享:小程序在渲染的时候,大多数组件都是渲染成 HTML 组件,但是有少部分比如 canvas、 video、 input、 map 等会渲染成原生组件的。所以,如果你在写小程序时,想用一段文字覆盖在一个 canvas 上,发现怎么设置都无法实现,那是因为 canvas 渲染后是原生组件,而文字是 html 组件,所以无法覆盖上去的 。那有什么办法呢?可以考虑把文字放到 cover-view 上, 它也是一种原生组件,可以覆盖在 canvas 上的。具体的可以参考小程序官方文档 原生组件说明

关于2018踩的坑就写到这里了,当然还有一些其他的,暂时没有时间整理,下次如果整理后,再写一篇补充一下。

如果大家有什么问题,或者过去踩到过了哪些坑,欢迎在评论区讨论哈。

掘金年度征文 | 2018 与我的技术之路 征文活动正在进行中......

我的2018前端踩坑记 | 掘金年度征文相关推荐

  1. 一位前端 2018 绝地求生记 | 掘金年度征文

    自我介绍 国际惯例先自我介绍.我叫 lien,17 年毕业于双非大学非科班,是一位玩了 3 年视频后期,在网易游戏做了 1 年视频后期与活动运营. 在某次机缘巧合,程序员同事给一些网站给我看濒临灭绝动 ...

  2. 一个前端的2018总结,2019展望 | 掘金年度征文

    2018年总结: 我是技术胖,我来参加征文了,其实我在2018年年底时,写过一篇总结文章了,看来是写早了. 开篇改版大江大河里的一句话: 作一个程序员12年了,我一直把技术当成理想,这理想是我心里的光 ...

  3. 从我想,到我做 | 掘金年度征文

    前言 感谢在屏幕前驻足的你. 自我介绍 大三网工学生,我就是你身边那个仿佛做了很多事情,身边的人都觉得你很努力,甚至曾经努力到自己被自己感动?某天蓦然回首却发现不曾成事的 boy. 幸好及时悬崖勒马, ...

  4. 新的起点,心的征程 | 掘金年度征文

    前言 世上本没有昨天,更没有未来. 人,说到底还是感性动物,对自己的曾经,或怀念,或悔恨:对自己的未来,或憧憬,或担忧. 站在新的起点,感怀过去,不惧将来,我将整理好当下的自己,踏上属于自己 IT 路 ...

  5. Vue + TypeScript + Element 搭建简洁时尚的博客网站及踩坑记

    前言 本文讲解如何在 Vue 项目中使用 TypeScript 来搭建并开发项目,并在此过程中踩过的坑 . TypeScript 具有类型系统,且是 JavaScript 的超集,TypeScript ...

  6. python从入门到实践django看不懂_Python编程:从入门到实践踩坑记 Django

    <>踩坑记 Django Django Python 19.1.1.5 模板new_topic 做完书上的步骤后,对主题添加页面经行测试,但是浏览器显示 服务器异常. 个人采用的开发环境是 ...

  7. 一个半路出家的前端工程师的2018 | 掘金年度征文

    自我介绍 国际惯例先自我介绍.我叫煤球,毕业于西安北雷村男子技术学院,当时在学校的时候也是浑浑噩噩的过来了,2015年毕业之后在一个国企工作,一直从事方案策划类的工作,由于是在不喜欢这种文案类的工作, ...

  8. 在百度地图中叠加CAD图及GIS数据展示踩坑记

    前言 在之前的几篇博客中分别介绍了 在Cesium中实现与CAD的DWG图叠加显示分析 https://www.cnblogs.com/vjmap/p/16541751.html . 高德地图与CAD ...

  9. 一个前端初学者的2018年终总结 | 掘金年度征文

    前言 "本文是一篇个人年终总结",这样听起来会不会高大上一点呢? 如果您正好浏览到这篇总结,可否邀请您认真读完此文.无需您的点赞,但是若能留下您 宝贵的建议,是再好不过了. 写这篇 ...

最新文章

  1. LeetCode 53. Maximum Subarray--动态规划--C++,Python解法
  2. postfix邮件过滤
  3. 分分合合分分,谷歌医疗走向大败退
  4. 用Thread实现socket多线通讯
  5. 轻轨与地铁有什么区别吗?
  6. 一个maven错误:org/apache/maven/shared/filtering/MavenFilteringException
  7. 《敏捷可执行需求说明 Scrum提炼及实现技术》—— 3.1 运用试错法
  8. 2019: 属于BERT预训练语言模型之年
  9. 泛型的继承和通配符,同时归纳集合部分的面试点
  10. python常用函数及用法
  11. Python机器学习笔记 GridSearchCV
  12. 【三维目标检测】PointRCNN(二)
  13. 音乐专业如何利用计算机思维,太神奇了!带学生“玩音乐”居然可以打开思维创新...
  14. django网页倒计时(完整代码,下载即可运行)
  15. 你还记得大明湖畔的我吗?来自黑莓的呼喊
  16. TFN DG15M 高抗干扰电缆故障测试仪评测
  17. 应用集成与数据集成建设总体思路
  18. 微信新表情真的太骚了!!
  19. 《面试无忧》--DCL单例模式为什么要用volatile修饰?
  20. 静态路由Route不生效的解决方法

热门文章

  1. GTA5需要什么配置?
  2. VSCode编写Markdown设置输出PDF的页边距
  3. dnfpkf正在连接服务器,dnf怎么复制角色进PK服_关于PKF以及复制PKF的相关讲解_好特教程...
  4. 创业案例:比邻如何选择产品方向
  5. 币安 PUBLIC API 示例
  6. 对接饿了么开放平台(Java)
  7. Java初学者作业——输入一个五位数字,计算各位数字之和并输出,运行结果为五个数字之和(实践2)
  8. Mars3D项目模板:基础项目 原生JS版 (widget方式)介绍
  9. 网络订餐时代,八大菜系的传统叫法过时了吗
  10. android手机怎么拆机,Android 4.0手机Galaxy Nexus拆解报告