何璇

15 天前

谈谈CSS sandbox的实现

本文作者:IMWeb 何璇 原文出处:IMWeb社区 未经同意,禁止转载

最近接了个需求,要实现一个FAQ页面。我心想那不简单嘛,就一个Tab加内容展示,结果最后排期还挺紧的,着实蛋疼了一小下。下面分享一些小心得:

问题

一开始实现这个页面都是怎么简单怎么来,监听Tab点击,然后向CGI请求到文章数据后,直接用Jquery渲染到页面上$('article').html(content)。很快你就发现,页面上展示的内容跟后台编辑的展示不一样。因为页面加载了一些公用的样式影响了文章的展示,比如:

  • reset.css
  • normalize.css
  • common.css

可以看下这个例子,在课程概述里其实是富文本的展示,但是目前大部分课程都选择自己PS作图上传上去。因为受到的影响实在太大了。

于是你需要要弄一个CSS sandbox来展示这个文章。

部分解决办法

命名空间

我第一个想到是命名空间,其实很简单,写过组件系统或者了解过H5制作器实现的人都应该知道,如何实现组件与组件之间的样式隔离,就是通过命令前缀来做的:

#namespace {
  h1 {
    font-size: 1.17em;
  }

  h2 {
    ...
  }

  ...
}

通过上述方式,我可以在<article id="article-sandbox">元素空间下,定义一套基本的样式,将common.css的影响去除。但是这样做一看就知道有很大局限性:

除了基础,页面样式是变化的,后台编辑的文章富文本内容也是变化的(而且会更复杂,以后可以能会增加音视频等),这些变化只要冲突就需要不断地修改此空间下的样式,重新发布,维护成本极高。

其实这样的方式在上面就已经提到适用于哪种场景了:

  • 类似H5制作器,需要将不同组件编辑拖放到同一页面展示
  • 内嵌的协议展示,因为基本上协议的内容标签是非常少的h1h6p,列表几个元素基本覆盖了

iframe

最后使用的方案是<iframe>元素,这是真正意义上的CSS沙盒。

顺带提一下,一开始为了图方便结合了data URL一起使用<iframe src="data:text/html,html string">,但是最后蛋疼的还是自己。

因为iframe方案其实也会带来许多局限性:

  • iframe高度不能自适应
  • 文章内嵌的链接点击在iframe内跳转
  • 文章内嵌视频播放状态问题
  • 文章内锚点需要通过外层的链接定位
  • 性能相关的问题
  • ...

最终还是通过与iframe之间的跨域通信来解决这些问题了。

shadow DOM

感觉shadow DOM简直天生迎合这个场景,但是由于它的兼容性不好一早就放弃了这个方案。

如果你不了解什么是shadow DOM,请先查阅https://www.html5rocks.com/en/tutorials/webcomponents/shadowdom/

一些题外话

其实在开发过程中还遇到一些其他问题,但由于时间精力有限,来不及深入进去探讨,这里简要提一下。

docx2html

(TODO...)

总结

以上是本人一些浅见,欢迎一起学习交流。

3条评论

    您需要 注册 一个IMWeb账号或者 才能进行评论。