zoukankan      html  css  js  c++  java
  • stylus笔记

    Stylus介绍及特点

    基于Node.js的css的预处理框架,其本质上做的事情与 Sass/LESS 等类似, 可以以近似脚本的方式去写CSS代码,创建健壮的、动态的、富有表现力的CSS,默认使用 .styl 的作为文件扩展名,支持多样性的CSS语法。Stylus比LESS更强大,而且基于nodejs比Sass更符合我们的思路。

    Stylus的特点如下

    • 基于js

    Node.js是一个Javascript运行环境(runtime),是对Google V8引擎进行了封装,V8引擎执行Javascript的速度非常快,性能非常好。对于不了解Node.js的开发人员,不会增加太多学习成本。Stylus基于Node.js,换而言之,就是借助JavaScript让CSS更富有表现力,更动态,更健壮!而且还有专门的JavaScript API。

    • 支持Ruby之类框架

    虽然Stylus基于Node.js,但是依然支持Ruby之类框架,还有FireBug插件FireStylus, sublimetext插件,便于开发、调试。

    • 功能强大,使用灵活,支持多样性的CSS语法

    Stylus的功能比LESS强大,不逊于Sass。在用法上,支持传统的CSS,而且相对于传统的用法,更加简洁、灵活,像省掉花括号、冒号,分号,甚至使用混合的CSS编程,Stylus都可以接受。

    Stylus的优缺点

    【优点】

    解决样式覆写的问题,尤其是mixin式复用

    使用纯CSS,我们可以抽象出一些常用的布局CSS属性组合,通过CSS的类组合来达成常见的mixin式复用,然而这种方案存在一些问题,例如:

    当页面重构时,需要频繁修改class name,这个问题在后端人员掌握着视图层的时候格外突出,前后端耗费很多沟通成本;

    在约束上下文的时候非常无力,比如“只有在ul下面的img.db允许是display:block”的规则,写成“ul img.db { display: block; }”就完全跑偏了,它违背了创建这个.db类时的本意,造成了代码的可读性和可维护性下降。

    如果你要改动规则,需要同时修改HTML和CSS,也可能造成新的样式问题。

    而通过Stylus可以建立一种新的代码风格,只允许CSS Class代表UI模块的抽象,这样一来,改动样式时不至于通知后端改模板,然后在CSS Class内部实现mixin。而这正是CSS的短板,CSS体系内的用法只有复制粘贴。

    可缓解多浏览器兼容造成的冗余

    进入CSS3的时代,旧式CSS hack如filter,新式兼容前缀如-webkit-等,都是冗余,修改的时候也需要修改多处,不容易维护。在Stylus里面,写个函数就能解决,多次复用也不需要看到如此之多的hack。

    提高效率,节约成本

    用Stylus开发CSS可以提高效率,它类似于一种CSS的方言,可以用更精简的语法表达更多的意思。比如,Stylus中可以使用变量,比如和 UED 同学订好各种样式的规范,做好变量后开发中直接使用,避免页面中的各种杂乱样式。当样式需求有变动时,也可以重新给变量赋值,一下改掉相关样式,不用再一点一点的改。

    使CSS开发更加灵活

    Stylus可以使用变量、条件、循环,兼容传统的CSS样式,等等,可以让CSS的开发和修改更加灵活。

    【缺点】

    开发过程增加步骤

    CSS的好处在于简便、随时随地被使用和调试,使用Stylus,增加了预编译CSS的步骤,让我们开发工作流中多了一个环节,调试也多了个步骤。

    增加学习成本。

    虽然Stylus简单易学,可以兼容传统CSS,但是当开发和维护团队都从CSS过渡到Stylus时,还是需要一点学习成本的,而且初学者使用起来,不一定能明显提高效率。

    语法:

    1. 选择器

    Stylus就跟CSS一样,允许你使用逗号为多个选择器同时定义属性。

    textarea, input
      border 1px solid #eee
    使用新行是一样的效果:
    
    textarea
    input
      border 1px solid #eee
    等同于:
    
    textarea,
    input {
      border: 1px solid #eee;
    }
    父级引用

    字符&指向父选择器。下面这个例子,我们两个选择器(textareainput)在:hover伪类选择器上都改变了color

    textarea
    input
      color #A7A7A7
      &:hover
        color #000
    等同于:
    textarea,
    input {
      color: #a7a7a7;
    }
    textarea:hover,
    input:hover {
      color: #000;
    }
    消除歧义

    类似padding - n的表达式可能既被解释成减法运算,也可能被释义成一元负号属性。为了避免这种歧义,用括号包裹表达式:

    pad(n)
      padding (- n)
    
    body
      pad(5px)

    编译为:

    body {
      padding: -5px;
    }

    然而,只有在函数中才会这样(因为函数同时用返回值扮演混合或回调)。

    有Stylus无法处理的属性值?unquote()可以帮你:

    filter unquote('progid:DXImageTransform.Microsoft.BasicImage(rotation=1)')
    生成为:
    filter progid:DXImageTransform.Microsoft.BasicImage(rotation=1)

    2.变量

    我们可以指定表达式为变量,然后在我们的样式中贯穿使用:

    font-size = 14px
    
    body
      font font-size Arial, sans-seri

    变量甚至可以组成一个表达式列表:

    font-size = 14px
    font = font-size "Lucida Grande", Arial
    
    body
      font font sans-serif      

    编译为:font: 14px "Lucida Grande", Arial sans-serif;

    标识符(变量名,函数等),也可能包括$字符。例如:

    $font-size = 14px
    body {
      font: $font-size sans-serif;
    }
    属性查找

    Stylus有另外一个很酷的独特功能,不需要分配值给变量就可以定义引用属性。下面是个很好的例子,元素水平垂直居中对齐(典型的方法是使用百分比和margin负值),如下:

    #logo
      position: absolute
      top: 50%
      left: 50%
       w = 150px
      height: h = 80px
      margin-left: -(w / 2)
      margin-top: -(h / 2)
    
    我们不使用这里的变量w和h, 而是简单地前置@字符在属性名前来访问该属性名对应的值: #logo position: absolute top:
    50% left: 50% width: 150px height: 80px margin-left: -(@width / 2) margin-top: -(@height / 2)

    3. 插值

    Stylus支持通过使用{}字符包围表达式来插入值,其会变成标识符的一部分。例如,-webkit-{'border' + '-radius'}等同于-webkit-border-radius.

    比较好的例子就是私有前缀属性扩展

    vendor(prop, args)
      -webkit-{prop} args
      -moz-{prop} args
      {prop} args
    
    border-radius() 
      vendor('border-radius', arguments)
    
    box-shadow()
      vendor('box-shadow', arguments)
    
    button
      border-radius 1px 2px / 3px 4px
    变身:
    
    button {
      -webkit-border-radius: 1px 2px / 3px 4px;
      -moz-border-radius: 1px 2px / 3px 4px;
      border-radius: 1px 2px / 3px 4px;
    }
    选择器插值

    插值也可以在选择器上起作用。例如,我们可以指定表格前5行的高度,如下:

    table
      for row in 1 2 3 4 5
        tr:nth-child({row})
          height: 10px * row
    也就是:
    
    table tr:nth-child(1) {
      height: 10px;
    }
    table tr:nth-child(2) {
      height: 20px;
    }
    table tr:nth-child(3) {
      height: 30px;
    }
    table tr:nth-child(4) {
      height: 40px;
    }
    table tr:nth-child(5) {
      height: 50px;
    }

    4.运算符

    运算符优先级:从最高到最低

    []
    ! ~ + -
    is defined
    ** * / %
    + -
    ... ..
    <= >= < >
    in
    == is != is not isnt
    is a
    && and || or
    ?:
    = := ?= += -= *= /= %=
    not
    if unless

    一元运算符, !,not, -, +,以及~     

    -5px
    // => -5px
    
    --5px
    // => 5px
    
    not true
    // => false
    
    not not true
    // => true

    not的优先级较低
    a = 0
    b = 1
    
    !a and !b
    // => false
    // 解析为: (!a) and (!b)
    
    

    用:

    
    
    not a or b
    // => false
    // 解析为: not (a or b)

    范围..  ...

    同时提供包含界线操作符(..)范围操作符(...),见下表达式:

    1..5
    // => 1 2 3 4 5
    
    1...5
    // => 1 2 3 4

    加减乘除余 + - * / %  :二元加乘运算其单位会转化,或使用默认字面量值。例如,5s - 2px结果是3s

    20mm + 4in
    // => 121.6mm
    
    "foo " + "bar"
    // => "foo bar"
    
    "num " + 15
    // => "num 15"
    
    2000ms + (1s * 2)
    // => 4000ms
    
    5s / 2
    // => 2.5s
    
    4 % 2
    // => 0

    当在属性值内使用/时候,你必须用括号包住。否则/会根据其字面意思处理(支持CSS的line-height)。

    font: 14px/1.5;
    但是,下面这个却等同于14px ÷ 1.5: font: (14px/1.5); 只有/操作符的时候需要这样

    指数:**

    相等与关系运算:== != >= <= > <

    相等运算符可以被用来等同单位、颜色、字符串甚至标识符。这是个强大的概念,甚至任意的标识符(例如wahoo)可以作为原子般使用。函数可以返回yesno代替truefalse(虽然不建议)。

    别名:

    ==    is
    !=    is not
    !=    isnt
    5 == 5
    // => true
    
    10 > 5
    // => true
    
    #fff == #fff
    // => true
    
    true == false
    // => false
    
    wahoo == yay
    // => false
    
    wahoo == wahoo
    // => true
    
    "test" == "test"
    // => true
    
    true is true
    // => true
    
    'hey' is not 'bye'
    // => true
    
    'hey' isnt 'bye'
    // => true
    
    (foo bar) == (foo bar)
    // => true
    
    (1 2 3) == (1 2 3)
    // => true
    
    (1 2 3) == (1 1 3)
    // => false

    只有精确值才匹配,例如,0 == falsenull == false均返回false.

    真与假

    Stylus近乎一切都是true, 包括有后缀的单位,甚至0%0px等都被认作true.

    不过,0在算术上本身是false.

    表达式(或“列表”)长度大于1被认为是真。

    true例子:

    0% 
    0px
    1px 
    -1
    -1px
    hey
    'hey'
    (0 0 0)
    ('' '')

    false:

    0 
    null
    false
    ''
    逻辑操作符:&& || 和 or

    逻辑操作符&&||别名是and / or。它们优先级相同。

    存在操作符:in

    检查左边内容是否在右边的表达式中。

    元组同样适用:

    vals = (error 'one') (error 'two')
    error in vals
    // => false
    
    (error 'one') in vals
    // => true
    
    (error 'two') in vals
    // => true
    
    (error 'something') in vals
    // => false

    混合书写适用例子:

    pad(types = padding, n = 5px)
      if padding in types
        padding n
      if margin in types
        margin n
    
    body
      pad()
    
    body
      pad(margin)
    
    body
      pad(padding margin, 10px)
    对应于:
    body {
      padding: 5px;
    }
    body {
      margin: 5px;
    }
    body {
      padding: 10px;
      margin: 10px;
    }
    条件赋值:?= :=

    条件赋值操作符?=(别名?:)让我们无需破坏旧值(如果存在)定义变量。该操作符可以扩展成三元内is defined的二元操作。

    例如,下面这些都是平起平坐的:

    color := white
    color ?= white
    color = color is defined ? color : white
    如果我们使用等号=, 就只是简单地赋值。
    color = white
    color = black
    
    color
    // => black

    但当使用?=,第二个相当就嗝屁了(因为变量已经定义了): color = white color ?= black color // => white
    实例检查:is a

    Stylus提供一个二元运算符叫做is a, 用做类型检查。

    15 is a 'unit'
    // => true
    
    #fff is a 'rgba'
    // => true
    
    15 is a 'rgba'
    // => false
    另外,我们可以使用type()这个内置函数。
    
    type(#fff) == 'rgba'
    // => true

    注意:color是唯一的特殊情况,当左边是RGBA或者HSLA节点时,都为true.

    变量定义:is defined   用来检查变量是否已经分配了值。

    该操作符必不可少,因为一个未定义的标识符仍是真值,如:

    body
      if ohnoes
        padding 5px
    当未定义的时候,产生的是下面的CSS:
    
    body {
      padding: 5px;
    }
    显然,这不是我们想要的,如下书写就安全了:
    
    body
      if ohnoes is defined
        padding 5px

    三元   

    num = 15
    num ? unit(num, 'px') : 20px
    // => 15px

    5.混合书写(Mixins)

    混入 混入和函数定义方法一致,但是应用却大相径庭。

    例如,下面有定义的border-radius(n)方法,其却作为一个mixin(如,作为状态调用,而非表达式)调用。

    border-radius()选择器中调用时候,属性会被扩展并复制在选择器中。

    border-radius(n)
      -webkit-border-radius n
      -moz-border-radius n
      border-radius n
    
    form input[type=button]
      border-radius(5px)
    编译成:
    
    form input[type=button] {
      -webkit-border-radius: 5px;
      -moz-border-radius: 5px;
      border-radius: 5px;
    }

    我们可以利用arguments这个局部变量,传递可以包含多值的表达式。

    border-radius()
      -webkit-border-radius arguments
      -moz-border-radius arguments
      border-radius arguments

    现在,我们可以像这样子传值:border-radius 1px 2px / 3px 4px!

    另外一个很赞的应用是特定的私有前缀支持——例如IE浏览器的透明度:

    support-for-ie ?= true
    
    opacity(n)
      opacity n
      if support-for-ie
        filter unquote('progid:DXImageTransform.Microsoft.Alpha(Opacity=' + round(n * 100) + ')')
    
    #logo
      &:hover
        opacity 0.5
    渲染为:
    
    #logo:hover {
      opacity: 0.5;
      filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=50);
    }

    父级引用

    混合书写可以利用父级引用字符&, 继承父业而不是自己筑巢

    例如,我们要用stripe(even, odd)创建一个条纹表格。evenodd均提供了默认颜色值,每行也指定了background-color属性。我们可以在tr嵌套中使用&来引用tr,以提供even颜色。

    stripe(even = #fff, odd = #eee)
     tr
       background-color odd
       &.even
       &:nth-child(even)
           background-color even
    然后,利用混合书写,如下:
    
    table
      stripe()
      td
        padding 4px 10px
    
    table#users
      stripe(#303030, #494848)
      td
        color white
    另外,stripe()的定义无需父引用:
    
    stripe(even = #fff, odd = #eee)
      tr
        background-color odd
      tr.even
      tr:nth-child(even)
        background-color even
    如果你愿意,你可以把stripe()当作属性调用。
    
    stripe #fff #000
    混合书写中的混合书写

    自然,混合书写可以利用其它混合书写,建立在它们自己的属性和选择器上。

    例如,下面我们创建内联comma-list()(通过inline-list())以及逗号分隔的无序列表。

    inline-list()
      li
        display inline
    
    comma-list()
      inline-list()
      li
        &:after
          content ', '
        &:last-child:after
          content ''
    
    ul
      comma-list()

    渲染:

    ul li:after {
      content: ", ";
    }
    ul li:last-child:after {
      content: "";
    }
    ul li {
      display: inline;
    }
  • 相关阅读:
    HDU 1556 差分,前缀和
    Full permutation
    PAT B1029
    字串简介
    阵列(3)
    完形填空
    关于c的比较
    19 阵列的复制
    switch述句
    阵列变数(2)
  • 原文地址:https://www.cnblogs.com/aimeeblogs/p/9508493.html
Copyright © 2011-2022 走看看