百科问答小站 logo
百科问答小站 font logo



为什么 CSS 这么难学? 第1页

  

user avatar   zhihusucks 网友的相关建议: 
      

没想到会这么多赞,早知道就不黑 CSS 了 T_T

CSS 不正交并不是对 CSS 的指责,如果能正交它肯定会做到正交的,现在的设计虽然不完美,但可能是最好的设计。

下文列举的问题能在规范里找到解释不能说明 CSS 是正交的,因为正不正交应该是从表面上就能看出来的。正交一般都是对接口的约束,具体实现我不管的。

本答案可以很好地解释「为什么你会觉得 CSS 难学」,至于不难的学习方式,其实是不存在的。要么你大量练习从实践中总结,要么你大量阅读文档从理论中领悟,反正 CSS 就是很难学。

我是这么觉得的,如果有人问 CSS 为什么这么难学,我们就应该好好回答 CSS 为什么这么难学;至于 CSS 多牛逼,应该另开一个问题。


短答案:因为 CSS 不正交。

长答案:

我先来解释一下什么是正交。

你调过显示器的「亮度」、「色调」和「饱和度」吧。

  • 「亮度」就是明暗程度,值越大,屏幕越亮。
  • 「色调」就是颜色,你通过调色调,可以把红色调成绿色。
  • 「饱和度」就是鲜艳程度,值越大越鲜艳。

「正交」就是,你调节这三者中的一个时,不影响其他两个效果。

  • 你调节「亮度」的时候「色调」和「饱和度」不会变化。
  • 你调节「色调」的时候「亮度」和「饱和度」不会变化。
  • 你调节「饱和度」的时候「亮度」和「色调」不会变化。

「正交」看起来应该是理所当然的,对吧。

想象一下「不正交」的情况:你调节「亮度」的时候,「色调」和「饱和度」会跟着无规律的变化。如果是这样,你会调得想死,因为你很难调到你想要的效果。


而 CSS,就是「不正交」的。

我以 width 对 margin-left 的影响为例,假设有如下代码:

.parent 里面的 .child 宽度为 300px,现在我给他添加一个 margin-left: -10px,会发现

整个 .child 左移 10 像素

好的,于是我们知道 margin-left: -10px 会让元素整体左移。

真的是这样吗?

这个时候把 width 去掉重新做实验,这是在添加 margin-left 之前:

这是在添加 margin-left 之后:

我们发现 margin-left: -10px 并没有让整个元素左移,只是让左边缘左移了,右边缘并没有动。

现在来总结一下:

  1. 如果指定了 width,那么 margin-left: 10px 会使元素整体左移
  2. 如果没有指定 width,那么 margin-left: 10px 只会使做边缘左移(也就是宽度扩大)

看到这里,你就会觉得 CSS 特别不正交:

  1. 为什么 width 的存在与否会影响 margin-left 的作用?
  2. 有没有 width 之外的其他属性也会影响 margin-left 的作用?恐怕你无法得知。

这就是不正交的恐怖之处,你只有把所有属性与 margin-left 一起用一下,才能得知 margin-left 的真正规律。

这还只是两个属性的影响,你能想象三个属性互相影响的情况吗?

P.S. 有些前端老手已经能「感性」地理解 width: auto 的意义,觉得这不是「不正交」。其实我只是举例说明「你无法只看一个属性就知道这个属性对应的效果,你必须结合另一个属性一起来看」。


我再举第二个例子,大家都知道 position: fixed 是相对于视口(viewport)定位的。

但是这个「真理」会受另一个元素的影响……对,我知道你很震惊……

先看正常情况:

网页右边是一个 iframe,红色的 .fixed 元素相对于 iframe 视口左上角定位,与我们预期一致。

接下来我在 .box 上面加一个 CSS3 中的属性,就会改变你的认知:

父容器加了 transform 之后,fixed 定位的元素居然相对于父容器定位。

天知道以后 CSS 会不会加更多元素来影响我已经认为是真理的事情?

我说一个更实际的问题吧,你敢在接手一个项目时,在任意一个元素上加 transform 属性吗?

你不敢!除非你把它的每个子元素的属性都检查一遍……确定没有 fixed 定位。

这就是「不正交」的恶心之处。


我再举一个例子,大家都知道给固定宽度的 div 加 margin: 0 auto 可以让它水平居中,很多人就问,那为什么 margin: auto 0(注意 auto 和 0 的位置反过来了)不能做到垂直居中呢?

其实是可以的:

但是必须是在当前元素有 position: absolute; top: 0; bottom:0; 的情况下才能垂直居中。或者与 flex 结合起来用也行。

这就很「不正交」了……


还有一些很常见的例子我就不一一详细列举了:

  1. border、padding、overflow、display:table、display:inline-block 会影响 margin
  2. position: absolute 会影响 display 和 float
  3. transform 会影响 z-index
  4. display 会影响 li 前面的小黑点 JS Bin

关键在于这些例子,要一个一个记,各属性被影响的情况都不一样!


CSS 最不正交的地方就是明明有 BFC,却非要把 BFC 藏起来,然后用 overflow:hidden 和 display: inline-block 等属性来触发 BFC。但用这些属性触发 BFC 总是会有副作用,这就是典型的不正交。

要触发 BFC 就单独发明一个触发 BFC 的属性不就好了。display: flow-root; 不就是在填这个坑嘛?所以你们说 CSS 是正交的,我肯定是不服的。


怎么学习「不正交」的东西?

有一个办法:试。

你试的组合情况越多,就越能了解各种奇怪的现象。

其实不用那么悲观,常用的组合也就几十种吧,都试出来并记下来就行了。


目前我们知道

  1. 不同属性的组合会有不同的效果;
  2. 新的属性会影响你已经学会的知识;
  3. 这些规律,毫无逻辑可言,你只能试出来。

这,就是 CSS 难学的原因。

以我的经验,越是理性的人,越难理解 CSS;越是感性的人,越容易理解 CSS。

这就是为什么大部分后端程序员能学会 JS,却学不会 CSS——他们太理性了。

你想用学编程的思路来学 CSS?放弃吧!

你需要用学画画的思路来学习 CSS——每天不停地画画,一个鸡蛋用不同的方式画一千遍,就成了。

所以我在课上说过一句话:

CSS 不是科学,CSS 是艺术。


不过凡事都有例外,如果你愿意老老实实看完 CSS 规格文档,然后再写 CSS,可能就不觉得有那么多不正交的地方了,但是有多少人有这个能力和精力呢?


P.S. 「正交」概念我是从《Unix编程艺术》学到的,少逛知乎多读书吧。


-----

微信 frank_fang 加好友请附上暗号:正交


----2018年10月更新----

为了把 CSS 讲清楚,我推出了这门课程


user avatar   Ivony 网友的相关建议: 
      

其实有这种感觉并不奇怪,因为你把CSS当作了一门程序设计语言一样的东西。


而事实上他只不过是一群醉汉拍脑袋胡乱发明出来的语焉不详的乱码的拼凑。

近年已经好太多了,早期的程序员甚至要通过调试了解浏览器会如何处理CSS并试图用这个玩意儿去控制浏览器的处理行为得到自己想要的结果。

这是一种极其高端的编程技巧,就像通过你的计算器的一些Bug写个游戏出来一样。唯一的好消息是,CSS实现的Bug实在太多了,使得你真的可以用这些Bug来编写程序。



反对所有认为CSS是一种正儿八经的编程语言的说法,CSS事实上是这样一种编程语言,其中占绝大多数的组成部分是UB(未定义的行为)。(至少在2.x之前的版本就是这样的)


刚去W3C网站上去看了下,似乎CSS 2.x以前的版本都已经被美化或者删除了,如果你能找到原始的文档去看一下,你就会知道没搞懂这玩意儿怎么会造成各种奇怪的效果,压根儿不是你的错。



CSS这玩意儿完全就是搞排版的那群人弄出来的玩意儿,毋庸置疑的是,他们的思维模式和写程序的完全不一样。

举个简单的栗子,作为程序员,当我们看到width的时候,我们会本能的询问,which width?是框的?内容的?实际展现的?设置的?包含填充的?父元素的?

而对于CSS的设计者而言,他觉得width is just width,这是很显然的事情……

有个好消息是,现在终于有程序员加入CSS工作组了。他们终于知道程序员要的是tell me behavior,而不是width is just width。


还有很多人非要杠width的问题,这样吧,我直截了当的问你:

         <table width="100px" cellspacing="0" border="1"><tbody><tr><td>a</td></tr></tbody></table>   <img width="100px" height="20px" border="1">   <div style="width: 100px"></div>   <table style="width: 100px; border: 1px;padding: 5px;" border="1"><tbody><tr><td>a</td></tr></tbody></table>   <img style="width: 100px; height: 20px; border: 1px;">     

你能画出来这五个元素的正确的宽度吗?

不问清楚width到底是什么东西能达到我们想要的效果吗?


说CSS标准系统规范的,你能画出来下面这段HTML实际的显示样式吗?

       <div style=" border: solid 1px;">   <span style="font-size: 20px">fptABC</span>   <span style="font-size: 40px">fptABC</span>   <span style="font-size: 80px">fptABC</span>   <img style="height: 50px; width: 50px; border: 1px; padding: 5px; margin: 5px;">   <span style="height: 50px; width: 50px; border: 1px; padding: 5px; margin: 50px; font-size: 40px;">fptABC</span> </div> abc     

多么简单的代码。所以,img的基线在哪里?span的又在哪里?margin会不会冲出外框?下一行的元素又怎么对齐?

你说这是个描述性语言,好啊,你告诉我这样描述出来的玩意儿唯一的符合标准的行为是什么?


我们要的是唯一确定的行为,不是TMD什么TMD描述。



另一个可以体现CSS设计狗血的地方在于默认样式。

我们知道事实上HTML元素都有自己的默认样式行为,在没有任何CSS样式设置的时候,他们就会呈现出这种默认样式行为。

但是,在漫长的时间里面,CSS压根儿就没有覆盖这些原本就有的默认样式行为。这就带来了大量的面向行为编程,例如table布局。

并不是程序员喜欢用table来布局,而是table的默认样式行为(制造一个可以垂直居中的盒子)压根儿没有办法用CSS来表示(直到flexible box的加入)。为了达到这样的效果,我们不得不搞一个table来控制浏览器的行为……



====================================================


就拿评论中的最常见的垂直居中的问题来说吧,在CSS里面我们怎么让一个块元素在页面居中呢?

我们得写成这样:

       <body style="display: flex; height: 100vh; box-sizing: border-box; margin: 0px; align-items: center; justify-content: center;">   <div>   </div> </body>     

这么多样式到底是干啥的?

一个个来解释:

  • box-sizing: border-box,用于定义后面设置的的高度为边框盒子高度而不是匪夷所思的内容高度,这几乎是布局所必需的。
  • margin: 0px,因为margin在边框盒子外面,所以还得把这个干掉。
  • height: 100vh,这三个属性加一起才能真正实现body元素的外框高度与浏览器视窗的高度一致。
  • display: flex,用于把body变成一个用于布局的弹性盒子
  • align-items: center,垂直居中
  • justify-content: center,水平居中


事实上我们用了三个属性才完成了这一件创举,让我们的body的高度与浏览器视窗的高度一致,这就是CSS设计者的脑回路。

再用了三个属性才使得我们的内容在水平和垂直两个方向都居中。


更别提这里面的box-sizing、flex和vh单位都是HTML5之后才出现的。说白了,整个flex体系都是微软和谷歌的程序员介入后才真正搞出来的。


在没有这些东西之前,唯一的方法就是做个table,然后那些大师们还叫嚣着,不要用table,用盒子,用盒子……

在没有flex和grid之前,盒你!@*&^&!*……


user avatar   wang-bin-1-53 网友的相关建议: 
      

实名反对以上所有给css难学洗地的人(哈哈,终于又可以装回逼了,来吧,欢迎撕逼)

CSS难学,方应杭 @方应杭 的答案我很赞同。正交性,姑且不论这个其他行业的专业术语来形容好不好,但他表达的思想是非常正确的:设计api或者框架的时候,一定要注意一个api影响的范围足够小,尽量一个api只干一件事。

而CSS完美的破坏了这个规则。

就这样,还有一堆给CSS洗地的,我也是醉了。让我们来看段洗地的评论:“这些在CSS规范里都写的很清楚,并且是可以推导的”。规范写的再清楚,和CSS设计理念就出错有什么关联?要记住,任何编程工具都是为人服务的,他们是轮子,是工具,是为了让人提高生产效率的。一切和这个目的相矛盾的设计都是反人类的。这点上虽然我不赞成轮子哥的wpf的前景问题,但CSS像杂耍似的我很支持。CSS撸了一堆隐藏规则,为什么设计之初不尽量避免这种设计、做到望文生义,而是隐藏在那几千页的规范里?CSS是给人用来画UI的,不是让你先学个几千页规范的。这目的就搞错了。假如你是一个框架的设计者,你撸了一堆互相影响、可能各种潜规则的api,然后告诉接手的哥们,“我这里面潜规则很多,你先看看那几十页的文档”,你看看会不会被人打?

来看个方应杭的例子。Transform这玩意加上之后,fixed 定位的元素居然相对于父容器定位。我当然知道规范里肯定有写这条规则,也知道这么做的理由。但这不是洗地的理由。为什么设计的时候非要加上这条原则?如果不加这条原则是否会引发更大的麻烦?如果非要加上的话,是不是应该在名字上加点修饰词而不是光突突一个Transform?更进一步,这样设计会不会给浏览器实现起来带来性能上的开销?

其实我觉得用“潜规则”这词来代替“正交性”来形容可能更好些。CSS里面潜规则简直多如牛毛。比如margin、padding的默认值,基本BAT三家的的网页都是一开头就全部清0了。搞个傻了吧唧的默认值,除了给大家制造麻烦,以及让大家多查规范文档,不知道还有啥鸟用。还有“inline-block的基线是最后一行文字的底部,flex里面的基线是第一行文字的底部”、“只有一个元素属于inline或是inline-block水平,其身上的vertical-align属性才会起作用”等一堆堆的潜规则。不要说这些潜规则文档里都写了。好的设计架构务必做到望文生义,看名字能知道用法,而不是靠别人查文档。记忆这些潜规则终究是需要脑力负担的。你第一次学的时候记住了(当然也可能被坑过才记得),过段时间说不定忘记了呢?会不会又被坑一次?所以什么文档详细记载了、规则都是可推导之类的托词真不是CSS设计各种缺陷以及容易学的理由。

CSS的设计缺陷还体现在各种浏览器的兼容性上面。大家以为是因为浏览器兼容性问题导致CSS难学,其实事实是反过来也成立。CSS的各种潜规则已经导致了就算是chromium的开发人员也经常各种被坑的程度了。打开chromium.googlesource.com看下每天多少提交都是关于修复实现中完善各种潜规则带来的坑。有人说刚学css,不必考虑浏览器兼容性。但事实是你的产品要用到生产中就肯定会遇到兼容性问题。因为不光各种浏览器之间CSS实现方式不一样,浏览器不同版本之间实现方式和表现也不一样。这很大部分原因就是CSS里潜规则太多导致的。

利益相关:微信X5内核苦逼排版工,曾经每天各种改chromium的排版bug。

未完待续,想到了继续喷…

最后放波硬广:屌炸天的内核来袭,史上最小chromium内核miniblink!

小巧的魔改版blink,嵌入作为浏览服务组件的最佳选择。现在已经继续开更了。


user avatar   davidtsang 网友的相关建议: 
      

CSS不容易掌握。特别是对于程序员来说,它这个东西很难找到最优解或者规律,太多的hack和奇淫巧技,你不明白为何代码整整齐齐,然后CSS渲染出来就是东跑西跑,或者位置偏移了几个pixel。经验大于技术,所以蛮头疼。我觉得很重要的一个原因是没有好书可以参考。我看过一本CSS实战的书,感觉可以学到一些东西,但是看完之后,你没有一种我懂了的这种感觉,只是好一点而已。你永远没有学完一门程序语言应有的那种我基本懂了的感觉。

css实战 - 图书 - 亚马逊


user avatar   ling-jian-94 网友的相关建议: 
      

真·天龙人来了。

我屁股下的这个embody罗技款不知道值不值天龙人的一台电脑?

不知道有几个天龙人当初跑到香港自提首发四公主?

不知道天龙人的电视几万?我这个早买的了,75z9d。psvr也是入的首发。

再比比打机环境?

朋友帮忙给我找的原价国行。(不帮买,朋友的店里之前就已经排队到了一百多人)



这电脑在天龙人里什么水平?为了玩4k的原神换的xg43uq和3080,纯娱乐用,非图形工作者。

其他小玩意就不显摆了。

就想说一句话,玩个游戏还玩出优越感的都是什么心态啊????

之前看了一个回答说得很好,你以为你是婆罗门,实际上在别人眼里你们都是印度阿三。

拿原神对比3A,想得出来什么结论?原神比不上那些3a,所以原神玩家就比不上3a玩家?我呸,那游戏是你做的?


装半天13其实没有真正回答这个问题,因为觉得懂得都懂,但是鉴于一些朋友很“幸运”没有接触过这类人,我就多唠叨几句。

天龙人,不是单机玩家(我就是单机玩家)的代名词,是以玩过看过听过甚至知道3a大作为荣的一群人。就像百万塞尔达不是指野炊玩家(我就是野炊玩家),而是看着像就说抄袭,像疯狗一样攻击别人,疑似水军的人。

天龙人鄙视原神,但是原神在进步,成绩也越来越好,打了曾经预言原神会暴毙人的脸。

玩家喜欢原神,自然热度高,还会夸,但这在天龙人眼里就是尬吹,他们通过用3a顶级大作去对比原神,说明原神辣鸡,去鄙视原神玩家,各种侮辱性的模版语录被传播,逻辑不严谨,但侮辱性极大。

其中最让我无法接受的就是“玩过好游戏的不可能玩原神”,“你觉得原神做得好是因为你没玩过好游戏”。这两句话把天龙人的优越感体现的淋漓尽致,何不食肉糜溢出屏幕,且不说画风不同,萝卜白菜各有所爱,就是人们的时间和设备也有很大差别,选择哪款游戏喜欢哪款游戏是玩家的自由,你哪来的脸指指点点说三道四?更何况,我遇到的很多说这话的人只是知道几个游戏,甚至玩盗版,模拟器,属实是精神天龙人了。

所以你喜欢鄙视是吧?那我就让你尝尝被鄙视的滋味。


玩家“尬吹”原神有没有错,个人认为只要不到处ky,踩一捧一,那吹一吹没问题。换位思考,我吹过p5天下第一,mhw天下第一,血源诅咒天下第一。

这时候有个不玩游戏的过来和我说,“什么电子海洛因就天下第一?玩游戏玩傻了吧?玩游戏有什么意思,几百几千的东西,来玩模型/文玩/改装车啊,随便一件就顶你们一堆。”

大家觉得这话有错吗?人家说的没错啊,确实一个模型几千上万,一件好的文玩也价格不菲,确实顶一堆。

但这人说话合适吗?太欠揍了,因为大家本就不是一个圈子的,我玩我的,碍着你了吗?你有病啊跑我这来?

同理,天龙人跑到原神这来用3a对比也是这样。有人可能会说,原神和3a同属游戏,是一个圈子。真的是吗?原神虽然上了ps5,但他的模式和以往的单机作品是不一样的,他可以算作是一种网游,生产周期,盈利模式,游玩设备,和以往的几年出一作的传统单机完全不一样,玩家群体也很不相同,根本不算一个圈子。

如果你觉得是一个圈子,那我没啥好说的,游戏/模型/文玩还都属于休闲娱乐圈子哩。

所以大家明白为什么天龙人用3a对比原神恶心了吗?首先主语是天龙人,他的对比就不是想好好对比,而是粗暴的把3a当武器,去攻击原神和玩家。其次这群天龙人见不得别人吹原神,跑到圈子里来恶心人。最后您要想说原神圈子里也有恶心的人,这我承认,哪个圈子没极端?甚至我看到这种言论也说他两句。当然如果你认为你遇到的所有原神玩家都极端…那请你先审视下自己的话有没有问题吧。我见过不少说原神玩家听不得别人说原神的一点不好。我翻看他的资料看他说的“一点不好”,呵呵,全是偏见与傲慢。不被喷才怪。


哎,管理员告诉我不样挂人,行吧,我都删了,反正大家知道有几个特别懂礼貌的高贵天龙人来私信我请我喝欧泡果奶就行了,咱也不知道咱是ky了还是尬吹了,现在以其人之道,还治其人之身也要被骂了?反正这些人不是破防了,一定不是。

还有某位同学呀,坐井观天不可取,你不能自己还啃老呢,就觉得别人都啃老。我啃我自己,放我自己家的照片也碍着您了?想反驳我也要找好角度是不是?你看看评论区有几个朋友反驳的就很好,当然他们要是能对天龙人也一视同仁就更好了。


再次声明,本人觉得一个人一个活法,一个人一个爱好,鄙视链装13不可取,本无意扮小丑,只是以暴制暴,恶心天龙人,非天龙人请勿在意,如引起您的不适我先道歉了。


请大家友好交流,很多评论不予显示或者被删除了,这里面没有一条是我删的,都是系统判定不友善。




  

相关话题

  vue等前端框架最直接的作用是什么?有大佬发表高见吗? 
  Vue 打包的 html 怎么样禁止打开 F12 开发者工具呢? 
  HTML、CSS、JavaScript 为什么不加个标明运行版本号的语法? 
  如何评价应届生前端人员月薪要3.3k到13k后,该公司CEO的评价? 
  Web 前后端分离的意义大吗? 
  前端工程师讨厌写 CSS 是什么心态? 
  为什么 CSS :not 选择器不支持复杂选择? 
  公司拖欠后端工资逼急了可以删库跑路,逼急了前端该如何何去何从? 
  JavaScript 中,定义函数时用 var foo = function () {} 和 function foo() 有什么区别? 
  前端当前是否处在一个糟糕的时代? 

前一个讨论
为什么拉斯维加斯枪击案后数日内,部分美国枪支类股价上涨?
下一个讨论
Mac 下有哪些能极大地提高工作效率的软件?





© 2024-09-19 - tinynew.org. All Rights Reserved.
© 2024-09-19 - tinynew.org. 保留所有权利