有哪些经常被误用的 HTML、JavaScript、CSS 的元素、方法和属性?

-

以前想要把一个元素(input 之类的)设成只读的时候都是用 disabled,后来发现这是不对的。 因为在 HTML 里面,如果一个元素被设置成 disabled, 那么它的值就不会被发送到 server 端。 正确的做法应该是使用 readonly。

那么除了这个 disabled,在 Web 开发中还有哪些东西是经常被误用的?

HTML CSS JavaScript CSS3

泻药!
仅说一下 CSS 方面的吧。

  1. float:left/right 或者 position: absolute 后还写上 display:block,画蛇添足(三者关系:Visual formatting model

  2. 不分场景的使用 overflow:hidden 来闭合浮动(详见:那些年我们一起清除过的浮动

  3. 为了让 Chrome 这个脑残支持小于12px 的文字,在 html 设置 -webkit-text-size-adjust:none; (最新的桌面版该属性已经被删除了,变更集:Changeset 145168)
  4. 认为 px 是一个绝对单位(px 是相对单位),整个页面都是 px,line-height 也用 px,全家都是 px

  5. 习惯性不分场景的去除 a 标签 focus 时候的焦点
  6. 认为布局就是 Float,所有的地方都是 Float,全家都是 Float!(试试 inline-block inline-block 前世今生 吧,试试 Flexbox 吧)
  7. 满页面都是用 .clearfix 来闭合浮动,如果已经有了BFC为嘛还要在闭合浮动呢?毒害不浅,某浪微博为例,102个 .clearfix


好吧我还是说点其他的吧:
  1. 搞不拎清 PNG 的分类,认为 PNG24 支持透明,不知道 PNG8 也支持 α 透明(可以看看:PNG的秘密
  2. 我又要吐槽 Label 不加 for ,或者 for 属性加的不对的问题(请看:雅安地震,前端开发者可以做什么?
  3. 看到@贺师俊老湿说道 ul,ol 滥用的问题,我举一个本来应该用 ol 却写成 ul 的例子:
    首页 | 微吧 一起扎堆吧!找反面教材,都去渣浪吧,渣浪你承认不?

  4. 查看源码,满屏都是 div 的就不多说了吧……
好吧,我已经原谅你们了,或许你遇到了学习瓶颈:
图片来源:《CSS 进阶之路》skydrive.live.com/?

延伸阅读:在 CSS 布局中,用 float 好还是用 position 好?分别有什么优势?

以上都是片面或者不对的!
一丝

table!!

我一定要为table正名~~table 谈不上误用,但绝对是被最被误解的一个标签, 无论谁都在说div+css,却没有去注意过多的标签的语义化,我清楚的记得我做的一东西发给别人看的时候别人用极其鄙视的口气跟我说,居然还用table!!

table 是用来定义 表格 的,所以在显示数据表格的时候就应该用table,而不该用其他的,事实上当你需要显示数据表格的时候,使用table也会方便很多。

至于,table的误用,就是用table来进行布局,但现在几乎很少人这么做了,哪怕新手~

最后 感谢 @一丝 的答案~~~

没人谈谈JS?呃,我今天又听到一种奇怪的说法,所以打算写几句。下面谈到的几点,可以说都是因太过「想当然」,想当然以为如此,却并没有去验证,错误的写法就这样一直流传着。

第一个,今天刚见到的,画蛇添足的 if (!!value)

if(value) if (!!value) 语义上没有任何区别。我反对if (!!value)的写法。
同样无聊的写法还有:if ((var1 == var2) == true)

if 接受“A condition expression that evaluates to true or false”,并非必须PrimitiveBool类型。
在《ECMAScript Spec》中,if (value)的语义相当于:IF (ToBoolean(value))。
而Logical Not的语义相当于:not ToBoolean(value)。
!!val 相当于 ToBoolean(value)。
也就是说:if (!!value)的语义相当于 IF (ToBoolean(ToBoolean(value)))。
如果你认为这种写法是合理的,那你为什么不继续写道:
if (!!(!!value))、
if (!!(!!(!!value)))

……?

请君一读《What the Tortoise Said to Achilles》


什么时候需要使用Logical Not “!” 转换类型呢?一般函数传参或返回值有这个必要。如果函数文档中说它返回一个Bool类型的值,那么函数作者就有责任保证其返回值的类型为(Primitive)Bool。因为函数的使用者可能会写出依赖返回值类型的代码:

/**
@returns Bool
*/
function has(str,substr) {
  return !!~str.indexOf(substr);
  //return ~str.indexOf(substr); // wrong!!!
}
//函数使用者的代码:
JSON.stringify({
  //此选项值类型早约定为Enum(0|1)
  xxxOptionOnOff:+has(s,"xxx") //使用者依赖于Bool to Number的转换
});

同作向函数传参也需要注意类型:

/**
@param {Bool} flag
*/
function toggle(flag) {
  //期望设置className为 toggle-on-true 或toggle-on-false
  //尽管不推荐这种过于依赖Bool参数类型的代码,但既然文档声明是Bool类型
  //传参者就有必要保证参数类型正确,即使是JS这种弱类型语言
  ele.className= "toggle-on-"+flag;
}
toggle(!!btn.checked);
//toggle(btn.checked); //wrong! btn.checked可能返回String "checked"

第二个,吃力不讨好的人肉GC:
有人喜欢在遇到闭包时人肉GC:
function foo() {
  var obj={/*May be a big object*/};
  return function () {
    //返回闭包中实际上没用到obj这个变量
    //没有用到的变量解释器本可作优化、不去捕获
    //但有人担心obj无法被GC,于是硬生生地...
    obj=null; // 于是解释器反而要将obj捕获了,笑~
    return;
  };
}
//还有人以为这样写就蛮好:
function bar() {
  var obj={/*May be a big object*/};
  //...lots of code
  obj=null;//那你以为它就*立即*被GC了吗?没有,同样画蛇添足。
  // 不过不排除有浏览器没有实现这种优化
  return function () {/*闭包中反正用不到obj*/};
}

第三个,效率系列,现在应该很少有人犯这些错误了:
  1. 以为 && 、 || 比 if 效率高。
  2. 以为 while (i) 比 while(i>0) 效率高。
  3. 以为 eval 永远效率非常低。
    这点已经有这篇文章讨论过:由eval生成的代码效率真的很差吗?
  4. 前置、后置的++、--系列的效率差别早在C语言中就被批的体无完肤了。
  5. 以为array[i]总比object[p]快,以致错误地使用了Sparse Array。
    ...想起了真正毁掉一切Array类型推导的:Array.prototype[9]="KAKA";
  6. 以为 …… 反正全都是以为怎么样怎么样。

第四个, `n|0`、`n^0`来取整不是始终OK的,Bitwise Operators先对Operand进行ToInt32,JS中的Number是双精度64位浮点数、不止Int32。Math.pow(2,32)|0 得 0

想想JS的常见错误确实不好找啊,每天修的Bug太多了,我能记得的Error肯定都是因为它不常见才记得它的啊。HTML、CSS写错了浏览器有时一声不吭,JS写错了就是写错了啊,错误留在那里迟早要见棺材的。

第五个,和jQuery有关的,你的代码中一般不应该出现element.unbind('event')这种Bug prone代码。这个调用是解除该事件所有监听函数,但仔细想一想,除非这个元素准备destroy掉了,这种代码一般是不应该出现的。如果该event所有监听函数都是自己绑定的,那你就应该知道当前Scene该unbind哪些listeners,很难想象绑定上去的listeners会多到超出管理能力unbind时懒得列举的情形;如果该元素是公共元素,其上会有其它代码bind上去监听函数,那这样写会导致或隐藏错误。而且重要的是,它通常是一个Bad Design信号,尤其当bind与unbind同时出现时。如果该元素/该场景没有准备destroy,这通常意味着我还会重复bind监听函数。如
editor.on("show",function () {
  submitButton.bind("click",function () {
    alert("Submit!"); //然后发现editor隐藏再show一次,就会alert执行两次
  });
});
editor.trigger("show");//触发一次show事件就会重复绑定一次代码
//为了FIX上面的问题,于是……
editor.on("show",function () {
  submitButton.unbind("click").bind("click",function () {
    alert("Submit!"); 
  });
});
没错,是Fix了Bug,但是,有没有更好的设计方式呢?有个原则是,绑定事件要趁早,根据不同的情况试举例说明,多出的unbind很可能是错误设计的信号:
//最低级的错误是,其实submitButton的行为不会受到editor状态的影响,它俩压根没关系
submitButton.bind("click",submitAction);//根本不需要等到show时再绑定
editor.on("show",showAction);

//另一种情况是,editor show时submitButton enable,hide时disable
function submitAction() {/*……*/}
function enableSubmit() {submitButton.bind("click",submitAction);}
function disableSubmit() {submitButton.unbind("click",submitAction);}
editor.on("show",enableSubmit);
editor.on("hide",disableSubmit);//那你一定忘记其实应在hide状态将其unbind
因为,bind与unbind本应在相反状态的两个Action中出现,如show与hide、enable与disable、on与off;如果不是,通常意味着bind事件与两个状态无关,既然与这些状态无关,为什么还要等状态触发再绑定呢? 若你发现会bind两次就意味着该状态会进入两次,既然会进入两次,就意味着该状态会退出,既然与状态有关,则应在一「进入」状态绑定,在另一「退出」状态解除,bind与unbind应始终保持这种对称关系,才有利于listeners的维护,避免Bug。而当你将bind与unbind分开时,你就会发现自己不会再写出 element.unbind('event') 这样草率的代码。

第六个, +new Date0 + new Date 是不一样的,当然我觉得这类坑都是JS设计上的错误,加法不符合交换律也就罢了,还非要将 Date类型特殊处理。

第七个,在Prototype上放一个NonPrimtive值(Object)作为Instance属性:
Editor.prototype={
  width:300, //default width 300 px
  toolbarItems:["File","Edit","Help"], //default toolbar items
  //……
  addToolbarItem:function (item) {
    this.toolbarItems.push(item); //Bug!
  }
};


好像我说的都是语法,都不是属性方法之类的啊。反正先写这么多,以后想起来再补充。

补充@一丝 的,
比如 a 和 a: link 大家会傻傻分不清楚。
比如一般人认为 margin 只有垂直方向才有 collapse。
比如,我以前认为 outerline 只有在 :focus 的时候才能用。
比如,绝对定位元素的参考区域是 padding - box,如果没有记错的话。

【Update】
写了 xhtml 的 doctype,但是文档连 well-formed 都没做到。比如渣浪微博。腾讯原来也是,不过最近似乎改好了。
【/Update】

几乎每个 HTML 标签都可能被用错,TABLE布局这种我就不说了,下面挑在各互联网大站屡见不鲜的说:

元素方面
1. 滥用 UL、DL
2. 该用 OL 的用 UL
3. 段落不会用 P 只会用 BR 和 DIV
4. 不会用 H1 / H2 / H3 ... 只会用 STRONG 甚至 DIV
5. 不会用 LABEL、FIELDSET、LEGEND
6. 乱用 ABBR、CITE、Q 之类比较少见的标签
7. 不会用或乱用 B / I / S / U 之类在 HTML5 中重新定义过的标签
属性方面
1. 多 class 症(病入膏肓的表现就是几乎每个元素上都有不止一个 class)
2. IMG 的 alt 属性没有意义(比如和title属性一样)
3. 混淆 INPUT 的 disabled 属性和 readonly 属性
4. LABEL 元素的 for 属性
5. 不会使用 lang 属性或 lang 属性写成 zh-CN 等已经废弃的用法

分不清JS转义字符、HTML转义字符、Url Encode。
还在使用escape函数进行Url Encode。
发布代码前不检查console调用(请借助工具)。
使用condition && do_something()的方式并自认为优雅(请用if然后让工具来帮忙压)。
做出了一个不能用回车提交的表单。
做出了一个tab顺序混乱的表单。
做出了一个输入时会被软键盘挡住的验证码(手机上)。
来当一个自定义事件的按钮。
使用缩写式变量命名,代码自带混淆属性。

滥用style、滥用ID、滥用js生成html、滥用css3特效、为了不使用table而不使用table(用层层div+css模拟)

这些东西被误用的情况,不胜枚举,其更深层次的原因在于编写者不求甚解抑或是没有这种意识不太care。手机打字可能有错别字,勿怪

看大家都写了这么多,顺手再加上一些:

1. 给block-level元素应用vertical-align,结果发现根本不生效;

2. 给inline non-replaced elements定义宽高,结果发现也不生效;

3. 给input/button定义line-height,试图实现垂直居中,结果个浏览器下的效果,让你崩溃,没弄清楚line-height的使用场景;

4. 给inline non-replaced elements定义垂直补白,结果又哭了;

5. 给非定位元素定义了z-index堆叠级别;

6. 给一个元素定义了opacity并且值小于1,发现有些元素被它盖住了,然后也懵了;

7. 给自闭合标签加了成对闭合,给成对闭合标签加了自闭合;

8. 把@import写到了其它规则集之后,结果还以为是自己的路径错了;

9. 真的在address标签里写家庭住址信息或者其他地址信息;

10. 完全把main, section, article, aside等当成div来用了;


简单列以上10条,这么做过的童鞋共勉,没做过的童鞋赞美一下。总之实际工作中误用乱用的例子实在太多,就不一一列举,希望引起大家关注并改善类似情况。

就说一个:html checkbox
这个标签坑爹的地方就在于:checked属性(也就是默认是否打勾的属性)的写法非常坑爹,一不留神就会写成是默认打勾的~~
正常情况下:

<input type="checkbox" checked="checked">
表明默认打勾的,
不过:
<input type="checkbox" checked="true" />
<input type="checkbox" checked="yes" />
<input type="checkbox" checked="no" />
<input type="checkbox" checked="" />
甚至:
<input type="checkbox" checked>
都全是表示默认打勾的!

那么怎么样才算是默认不打勾?只有“checked”字样不在标签中出现时。
stackoverflow上有一篇讨论就是有关这个话题的:
What is the syntax for boolean attributes, e.g. a checked checkbox, in HTML?

见过的,算不算

© COPYRIGHT BY i How And Why.com 2015