关于界面的价值观与方法论

把CSS全部归零

7March2009

我曾经佩服过google ads,它可以再任何网页上出现,而它的样式却不会被寄主网页的CSS给破坏。后来发现它其实是用的iframe,呵呵。

不过倒是引发了我一个思考:如何保证一个区域里的样式不会被外部样式“入侵”。要做到这点其实说难不难,说容易也不太容易。关键是两点:

1. 将该区域里的所有样式全部设为最初的默认值;
2. 保证上面的样式的优先级为最高。

所以呢,下面是一个尚未完善的例子:

#clearAllStyle *,
#clearAllStyle a:hover,
#clearAllStyle a:link,
#clearAllStyle a:visited,
#clearAllStyle a:active  {
    position: static;
    top: auto;
    right: auto;
    bottom: auto;
    left: auto;
    z-index: auto;
    
    float: none;
    clear: none;
    display: block;
    
    margin: auto;
    padding: 0;
    border-width: medium;
    border-color: inherit;
    border-style: none;
    width: auto;
    height: auto;
    min-width: 0;
    min-height: 0;
    max-width: none;
    max-height: none;
    
    color: #000;
    background-attachment: scroll;
    background-color: transparent;
    background-image: none;
    background-position: 0% 0%;
    background-repeat: repeat;
    
    font-size: 12px;
    font-family: sans-serif;
    line-height: normal;
    font-style: normal;
    font-variant: normal;
    font-weight: normal;
    text-align: left;
    text-decoration: none;
    text-indent: 0;
    text-transform: none;
    white-space: normal;
    letter-spacing: normal;
    word-spacing: normal;
    vertical-align: baseline;
    overflow: visible;
    visibility: visible;
}
#clearAllStyle span,
#clearAllStyle em,
#clearAllStyle strong {
    display:inline;
}
#clearAllStyle a
#clearAllStyle a:hover,
#clearAllStyle a:link,
#clearAllStyle a:visited,
#clearAllStyle a:active {
    display:inline;
    text-decoration:underline;
}

这个代码还处于待完善的阶段。我没有对其进行全面的测试,不过基本上能够保证绝大多数的情况了。

注意几点:
1. 我这里考虑的是将所有的CSS属性设为默认值,而并不是将所有的HTML标签设为它们默认的样式。因为其实从实践的角度,每个浏览器里HTML标签的默认样式都是不一致,不可能也没有必要将其回复到默认样式。保证样式不被外部样式入侵,这才是我们的目的。
2. 所谓的“属性的默认值”,是指在没有明确定义某个属性时,这个属性默认呈现出来的那个值。上面的值都是根据《CSS权威指南》里得到的,不过并不是所有的值都有默认值,没有的我就自己加了一个自己想要的那个值。
3. 有一个比较麻烦的问题:某些属性无法被子元素继承,比如text-align。倘若接下来有如下定义:

#clearAllStyle .copyright {
    text-align: center;
}

对于.copyright的子元素,就会仍然靠左。解决的办法是一个很傻的写法:

#clearAllStyle .copyright,
#clearAllStyle .copyright * {
    text-align: center;
}

看起来不好看,但是应该没什么大问题。
4. a标签在IE6下,其伪类的定义会被认为是最高优先级,所以需要显式声明。(感谢OoSleePinG指出)
5. 其他还有些元素需要被归为display: inline,比如del。但是,如果我其实不用它,就没必要写了。

如果大家有什么看法,欢迎进一步讨论。


  1. gneheix:

    我做backword的时候就遇到过这个问题

    听Ethan说你要搬到北新泾来了?

    lion

  2. Rock:

    遇到过这个问题,觉得完全没必要写的这么复杂.
    因为任何一个网站除了a或者指定区域的html标签都不会进行泛定义.

  3. OoSleePinG:

    感觉基于#clearAllStyle下的开发应该会很麻烦,
    #clearAllStyle内部会有两个问题
    1.上面说的继承问题,所有模块都要定义下 #clearAllStyle .module *{}比较麻烦的估计就是font 和 text,定义会很频繁。
    2.宿主网站页面应用浏览器私有属性问题,如果宿主站点对某个selector定义过某些浏览器下的私有属性也自然会影响到#clearAllStyle下元素的样式,概率比较小,要想解决又有点浪费。
    外部的问题就是优先级问题
    对于架构良好的网站来说,都会考虑到id优先级过高问题会避免或减少出现id,但#id#id这种的可能性也是很大的。
    其他问题就是a,如果主站已经lvha了那这必须也得来一下了,a的默认色彩该的站点也是很多的。

  4. 小麦:

    @OoSleePinG: 你说得对。所以我说是一个不完善的方案。

    不过如果类名起的独特,比如每个都加一个独特的前缀。大部分的冲突还是可以避开。甚至可以通过服务器端动态的变换类名。

    另外你讲的lvha问题很关键。THX。

  5. OoSleePinG:

    还一个很难避免的问题就是haslayout,一旦主站对某selector触发了haslayout,那后果还是很难想的。
    前缀是很好的解决办法。
    优先级还是问题,假若#id#id这样的selector的module 下有定义tag,其子元素有#clearAllStyle那影响是肯定的。

  6. diyism:

    From: http://diyism.com/?action=program.css_note

    制定css标准的时代还没有动态网页, 并没有考虑到区块内容变换, 因而css里没有类似”inherit:no;”的属性阻止继承,
    只能在区块顶层元素class属性内加’reset’来重置所有可继承属性来尽力阻止来自上层css的影响, ”.reset”定义段要
    放在”.tpl”定义之前以免影响区块css定义, 但阻止不了上层强指定值的影响:
    <!DOCTYPE html PUBLIC ”-//W3C//DTD HTML 4.01 Transitional//EN” ”http://www.w3.org/TR/html4/loose.dtd”>
    <style>
      span{float:left;vertical-align:middle;overflow:hidden;cursor:default;}br{clear:left;}
      #jjj{font-size:100px;}
      #jjj span{font-size:100px;}
      .reset{font-size:medium;}
      .tpl{font-size:20px;}
    </style>
    <span id=”jjj”>kkkkkkkkkk
        <span class=”reset tpl” style=”border:1px solid red;”>aaaaa</span>
    </span>
    可继承属性大致只有这些(见W3C_CSS21_Specification.chm的”Appendix F. Full property table”):
    (有些内建这几个属性的元素不会继承, 可设值为’inherit’以强制继承(firefox支持, ie用:”font-style:expression(this.parentNode.currentStyle?this.parentNode.currentStyle.fontStyle:’normal’);”)
    (font-family缺省值是浏览器默认字体, 无相应设置值, firefox里设置非法值可以覆盖继承值, ie6/ie7里仍用继承值,
    只好明设simsun, 在非中文系统里ie6/ie7认为simsun非法而仍用继承值)
    .reset {color: black;
            cursor: auto;
            direction: ltr;
            elevation: level;
            font-family: simsun,sans-serif;
            font-size: medium;
            font-style: normal;
            font-variant: normal;
            font-weight: normal;
            letter-spacing: normal;
            line-height: normal;
            text-align: left;
            text-indent: 0;
            text-transform: none;
            visibility: visible;
            white-space: normal;
            word-spacing: normal;
           }

    为了避免上层强指定值的影响, 只能制定一些自我约束原则来粗略满足ajax动态区块css独立性要求:
    在css rule的selector的各个级别:
    1.杜绝对tag或id定义样式(id for js, tag for html, class for css),
    2.杜绝使用”前辈 后辈”式选择(只用父子式选择, ie6要用expression实现).
    每个html小模板块对应一个css style块(供搜索引擎使用的公众页里)或css link文件(不怕文件零碎, 因静态文件浏览器会缓存, 而且ajax程序一个页面可能调无数小模板块(还可能是从外部网站调用的), 把css集中到一个文件不现实, 子模板也应该是一个一个的小文件),并且该css style块或css link文件内所有rule都以对应的html块的顶层class开头(最好前缀”tpl_”以跟下级class区分).

  7. 辉舞世间:

    我只学习,不发表意见……