Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

Following Stylus Learning and Using Stylus (PART 1), this paper summarizes the advanced usage of Stylus, including the remaining parameters, conditions, built-in methods, etc.

Stylus advanced usage

The remaining parameters

The remaining parameters

Stylus support name… Form the rest of the parameters. These arguments can digest the arguments passed to the mashup or function. This is useful when dealing with browser private attributes such as -moz or -webkit. In the following example, all the arguments (1px, 2px…) Are simply handled by a single args argument:

box-shadow(args...)
  -webkit-box-shadow args
  -moz-box-shadow args
  box-shadow args
#login
  box-shadow 1px 2px 5px #eee
Copy the code

For:

#login {
  -webkit-box-shadow: 1px 2px 5px #eee;
  -moz-box-shadow: 1px 2px 5px #eee;
  box-shadow: 1px 2px 5px #eee;
}
Copy the code

To specify a specific parameter, such as x-offset, you can use args[0], or you may want to redefine blending.

box-shadow(offset-x, args...)
  got-offset-x offset-x
  -webkit-box-shadow offset-x args
  -moz-box-shadow offset-x args
  box-shadow offset-x args
#login
  box-shadow 1px 2px 5px #eee
Copy the code

For:

#login {
  got-offset-x: 1px;
  -webkit-box-shadow: 1px 2px 5px #eee;
  -moz-box-shadow: 1px 2px 5px #eee;
  box-shadow: 1px 2px 5px #eee;
}
Copy the code

parameter

Arguments variables allow exact passing of expressions, including commas, and so on. This could make up for args… Some shortcomings of parameters, examples:

box-shadow(args...)
  -webkit-box-shadow args
  -moz-box-shadow args
  box-shadow args
#login
  box-shadow #ddd 1px 1px.#eee 2px 2px
Copy the code

The result is not desired:

#login {
  -webkit-box-shadow: #ddd 1px 1px #eee 2px 2px;
  -moz-box-shadow: #ddd 1px 1px #eee 2px 2px;
    box-shadow: #ddd 1px 1px #eee 2px 2px;
}
Copy the code

The comma is ignored. Now use Arguments to redefine the mixed writing.

box-shadow(a)
  -webkit-box-shadow arguments
  -moz-box-shadow arguments
  box-shadow arguments
body
  box-shadow #ddd 1px 1px.#eee 2px 2px
Copy the code

Get the desired result:

body {
  -webkit-box-shadow: #ddd 1px 1px.#eee 2px 2px;
  -moz-box-shadow: #ddd 1px 1px.#eee 2px 2px;
  box-shadow: #ddd 1px 1px.#eee 2px 2px;
}
Copy the code

conditions

conditions

Conditions provide flow control for a language that is otherwise purely static. Conditions are provided for import, mixin, functions, and more.

if / else if / else

As in normal languages, the following block is executed when the if expression satisfies (true); otherwise, the following else if or else continues.

In the following example, according to the overload condition, decide whether to use padding or margin.

overload-padding = true

if overload-padding
  padding(y, x)
    margin y x

body
  padding 5px 10px
Copy the code

Another example:

box(x, y, margin = false)
  padding y x
  if margin
    margin y x

body
  box(5px.10px, true)
Copy the code

Additional box() helpers:

box(x, y, margin-only = false)
  if margin-only
    margin y x
  else
    padding y x
Copy the code

Unless (unless)

Anyone familiar with the Ruby programming language should know the unless condition, which is basically the opposite of if and is essentially (! (expr)).

In the following example, if disable-padding-override is undefined or false, the padding is eliminated and a margin is displayed instead. However, if true, the padding will continue to print the padding 5px 10px as expected.

disable-padding-override = true

unless disable-padding-override is defined and disable-padding-override
  padding(x, y)
    margin y x

body
  padding 5px 10px
Copy the code

The suffix conditions

Stylus supports suffix conditions, which means that if and unless can be used as operators; The left-hand action object is executed when the right-hand expression is true. For example, we define Negative () to perform some basic checks. Here we use block conditions:

negative(n)
  unless n is a 'unit'
    error('Invalid value')
  if n < 0
    yes
  else
    no
Copy the code

Next, we use the suffix condition to keep our method simple.

negative(n)
  error('Invalid value') unless n is a 'unit'
  return yes if n < 0
  no
Copy the code

Of course, we can go further. If n is less than 0, right? Boolean: n < 0. Postfix conditions apply to most single-line statements. For example, @import, @charset, mixed writing, etc. Of course, the following attributes are also available:

pad(types = margin padding, n = 5px)
  padding unit(n, px) if padding in types
  margin unit(n, px) if margin in types
body
  pad()
body
  pad(margin)
body
  apply-mixins = true
  pad(padding.10) if apply-mixins
Copy the code

The result is:

body {
  padding: 5px;
  margin: 5px;
}
body {
  margin: 5px;
}
body {
  padding: 10px;
}
Copy the code

The iteration

The iteration

Stylus allows you to iterate over expressions through for/in in the following form:

for <val-name> [, <key-name>] in <expression>
Copy the code

Such as:

body
  for num in 1 2 3
    foo num
Copy the code

Generation:

body {
  foo: 1;
  foo: 2;
  foo: 3;
}
Copy the code

The following example demonstrates how to use

:

body
  fonts = Impact Arial sans-serif
  for font, i in fonts
    foo i font
Copy the code

For:

body {
  foo: 0 Impact;
  foo: 1 Arial;
  foo: 2 sans-serif;
}
Copy the code

Mixins

We can use loops for more power in mash-up, for example, we can use expression pairs as properties that use interpolation and loops. Next, we define apply(), using all arguments, so that comma-separated and expression lists are supported.

apply(props)
  props = arguments if length(arguments) > 1
  for prop in props
    {prop[0]} prop[1]

body
  apply(one 1, two 2, three 3)

body
  list = (one 1) (two 2) (three 3)
  apply(list)
Copy the code

Functions (Functions provides)

The Stylus function can also contain a for loop. Here is a simple example:

Sum:

sum(nums)
  sum = 0
  for n in nums
    sum += n

sum(1 2 3)                                    / / = > 6
Copy the code

Connection:

join(delim, args)
  buf = ' '
  for arg, index in args
    if index
      buf += delim + arg
    else
      buf += arg

join(', ', foo bar baz)                     // => "foo, bar, baz"
Copy the code

The suffix (Postfix)

Just as if/unless can take advantage of the following statement, so can for. Examples of suffix resolution are as follows:

sum(nums)
  sum = 0
  sum += n for n in nums

join(delim, args)
  buf = ' '
  buf += i ? delim + arg : arg for arg, i in args
Copy the code

We can also return from the loop, in this example, if n % 2 == 0 is true.

first-even(nums)
  return n if n % 2= =0 for n in nums

first-even(1 3 5 5 6 3 2)                           / / = > 6
Copy the code

@IMPORT

The import

Stylus supports literal @import CSS as well as dynamic imports of other Stylus styles.

Literally CSS

The file name of any.css extension as a literal. Such as:

@import "reset.css"
Copy the code

Render as follows:

@import "reset.css"
Copy the code

Stylus import

  • When using@importThere is no.cssExtension would be considered to beStylusFragments (e.g.@import "mixins/border-radius").
  • @importIt works as follows: traverses the directory queue and checks if the file is in any directory (similarnoderequire.paths). The queue defaults to a single path fromfilenameOf the optionsdirnameDerived from. So if your file name is/tmp/testing/stylus/main.styl, the import will appear as/tmp/testing/stylus/.
  • @importIndex form is also supported. That means when you@import blueprintIs understood to beblueprint.stylblueprint/index.styl.

The following statement:

@import 'mixins/vendor'
Copy the code

Is equal to:

.import('mixins/vendor')
Copy the code

@MEDIA

@Media works just as in regular CSS, but uses the block symbol of Stylus.

@media print
  #header
  #footer
    display none
Copy the code

For:

@media print {
  #header.#footer {
    display: none; }}Copy the code

@FONT-FACE

@font-face works just as it does in CSS. Simply add a block property to the end, for example:

@font-face
  font-family Geo
  font-style normal
  src url(fonts/geo_sans_light/GensansLight.ttf)
.ingeo
  font-family Geo
Copy the code

For:

@font-face {
  font-family: Geo;
  font-style: normal;
  src: url("fonts/geo_sans_light/GensansLight.ttf");
}
.ingeo {
  font-family: Geo;
}
Copy the code

@KEYFRAMES

@keyframes

Stylus supports the @keyFrames rule, which converts to @-webkit-Keyframes when compiled:

@keyframes pulse
0%
  background-color red
  opacity 1.0
  -webkit-transform scale(1.0) rotate(0deg)
100%
  background-color red
  opacity 1.0
  -webkit-transform scale(1.0) rotate(0deg)
Copy the code

For:

@-webkit-keyframes pulse {
  0% {
  background-color: red;
  opacity: 1;
    -webkit-transform: scale(1) rotate(0deg);
  }
  100% {
    background-color: red;
    opacity: 1;
    -webkit-transform: scale(1) rotate(0deg); }}Copy the code

extension

Using @keyframes, via vendors variables, the private prefix (Webkit Moz Official) is automatically added. This means that changes can be made instantly and efficiently at any time. Consider the following example:

@keyframes foo {
  from {
    color: black
  }
  to {
    color: white
  }
}
Copy the code

Amplify two default prefixes:

@-moz-keyframes foo {
  0% {
    color: # 000;
  }
  100% {
    color: #fff; }}@-webkit-keyframes foo {
  0% {
    color: # 000;
  }
  100% {
    color: #fff; }}@keyframes foo {
  0% {
    color: # 000;
  }
  100% {
    color: #fff; }}Copy the code

If we just want to have standard parses, it’s simple, modify vendors:

vendors = official
@keyframes foo {
  from {
    color: black
  }
  to {
    color: white
  }
}
Copy the code

For:

@keyframes foo {
  0% {
    color: # 000;
  }
  100% {
    color: #fff; }}Copy the code

Built-in methods

red(color)

Returns the red specific gravity in color.

red(#c00)                                   / / = > 204
Copy the code

green(color)

Returns the green proportion in color.

green(#0c0)                                 / / = > 204
Copy the code

blue(color)

Returns the blue specific gravity in color.

blue(#00c)                                  / / = > 204
Copy the code

alpha(color)

Returns the opacity proportion in color.

alpha(#fff)                                 / / = > 1
alpha(rgba(0.0.0.0.3))                      / / = > 0.3
Copy the code

dark(color)

Check if color is dark.

dark(black)                                 // => true
dark(# 005716)                               // => true
dark(white)                                 // => false
Copy the code

light(color)

Check if color is bright.

light(black)                                // => false
light(white)                                // => true
light(#00FF40)                              // => true
Copy the code

hue(color)

Returns the hue of the given color.

hue(hsla(50deg.100%.80%))                 // => 50deg
Copy the code

saturation(color)

Returns the saturation of the given color.

saturation(hsla(50deg.100%.80%))         / / = > 100%
Copy the code

lightness(color)

Returns the brightness of the given color.

lightness(hsla(50deg.100%.80%))          / / = > 80%
Copy the code

Push (expr, args…).

Then push the given ARgs to expR.

nums = 1 2
push(nums, 3.4.5)

nums                                      // => 1 2 3 4 5
Copy the code

An alias for the append ().

Unshift (expr, args…).

Insert the given ARGS into expR at the starting position.

nums = 4 5
unshift(nums, 3.2.1)

nums                                      // => 1 2 3 4 5
Copy the code

An alias for the prepend ().

keys(pairs)

Returns the key in the given pairs.

pairs = (one 1) (two 2) (three 3)
keys(pairs)                               // => one two three
Copy the code

values(pairs)

Returns the value in the given pairs.

pairs = (one 1) (two 2) (three 3)
values(pairs)                            // => 1 2 3
Copy the code

typeof(node)

The node type is returned as a string.

type(12)                                  // => 'unit'
typeof(12)                                // => 'unit'
typeof(#fff)                              // => 'rgba'
type-of(#fff)                             // => 'rgba'
Copy the code

The aliases can be typeof or type.

unit(unit[, type])

Return a string of type Unit or an empty string, or assign type without unit conversion.

unit(10)                                  / / = > '
unit(15in)                                // => 'in'
unit(15%.'px')                           // => 15px
unit(15%, px)                             // => 15px
Copy the code

match(pattern, string)

Checks whether the string matches the given pattern.

match('^foo(bar)? ', foo)                  // => true
match('^foo(bar)? '.'foobar')             // => true
match('^foo(bar)? '.'bar')                // => false
Copy the code

abs(unit)

Return absolute value.

abs(-5px)                                 // => 5px
abs(5px)                                  // => 5px
Copy the code

ceil(unit)

Round up.

ceil(5.5 in)                               // => 6in
Copy the code

floor(unit)

I’m going to round down.

floor(5.6 px.)                              // => 5px
Copy the code

round(unit)

Round off.

round(5.5 px.)                              // => 6px
round(5.4 px.)                              // => 5px
Copy the code

min(a, b)

Let’s take a smaller value.

min(1.5)                                 / / = > 1
Copy the code

max(a, b)

Take the larger value.

max(1.5)                                 / / = > 5
Copy the code

even(unit)

Returns whether it is even.

even(6px)
// => true
Copy the code

odd(unit)

Returns whether it is odd.

odd(5mm)                                // => true
Copy the code

sum(nums)

The sum.

sum(1 2 3)                              / / = > 6
Copy the code

avg(nums)

Take the average.

avg(1 2 3)                              / / = > 2
Copy the code

The join (delim, vals…).

Given vals use the delim connection.

join(' '.1 2 3)                       // => "1 2 3"
join(', '.1 2 3)                       / / = > "1, 2, 3"
join(', ', foo bar baz)                // => "foo, bar, baz"
join(', ', foo, bar, baz)              // => "foo, bar, baz"
join(', '.1 2.3 4.5 6)              // => "1 2, 3 4, 5 6"
Copy the code

hsla(color | h,s,l,a)

Convert the given color to an HSLA node, or h, S, L, A specific gravity value.

hslaa(10deg.50%.30%.0.5)            // => HSLA
hslaa(#ffcc00)                         // => HSLA
Copy the code

hsla(color | h,s,l)

Convert the given color to the HSLA node, or h, S, L specific gravity values.

hsla(10.50.30)                      // => HSLA
hsla(#ffcc00)                         // => HSLA
Copy the code

rgba(color | r,g,b,a)

Return RGBA from r, G, B,a channels, or provide color to adjust transparency.

rgba(255.0.0.0.5)                     / / = > rgba (255,0,0,0.5)
rgba(255.0.0.1)                       // => #ff0000
rgba(#ffcc00.0.5)                    / / rgba (255204,0,0.5)
In addition, the stylus supports the # rGBA and #rrggbbaa symbols.
#fc08                                 / / = > rgba (255204,0,0.5)
#ffcc00ee                             / / = > rgba (255204,0,0.9)
Copy the code

rgb(color | r,g,b)

Return RGBA from r, G, or B channels or generate an RGBA node.

rgb(255.204.0)                        // => #ffcc00
rgb(#fff)                             // => #fff
Copy the code

lighten(color, amount)

Given color brightening amount value. The method is unit sensitive, for example, to support percentages as follows:

lighten(#2c2c2c.30)                  / / = > # 787878
lighten(#2c2c2c.30%)                 / / = > # 393939
Copy the code

darken(color, amount)

Given color darken amount value. The method is unit sensitive, for example, to support percentages as follows:

darken(#D62828.30)                   / / = > # 551010
darken(#D62828.30%)                  // => #961c1c
Copy the code

desaturate(color, amount)

Decrease amount for a given color saturation.

desaturate(#f00.40%)                 // => #c33
Copy the code

saturate(color, amount)

Given color saturation increase amount.

saturate(#c33.40%)                   // => #f00
Copy the code

invert(color)

Color out of phase. The red, green and blue colors are reversed and the opacity remains the same.

invert(#d62828)                       // => #29d7d7
Copy the code

unquote(str | ident)

Given STR quote removal, the Literal node is returned.

unquote("sans-serif")                 // => sans-serif
unquote(sans-serif)                   // => sans-serif
unquote('1px / 2px')                  // => 1px / 2px
Copy the code

S (FMT,…).

The s() method is similar to unquote(), except that the latter returns a Literal node, whereas here it takes a formatted string, much like the C sprintf(). Currently, the unique identifier is %s.

s('bar()');                           // => bar()
s('bar(%s)'.'baz');                  // => bar("baz")
s('bar(%s)', baz);                    // => bar(baz)
s('bar(%s)'.15px);                   // => bar(15px)
s('rgba (% s, % s, % s, 0.5)'.255.100.50);   // => gba(255, 100, 50, 0.5)
s('bar(%Z)'.15px);                   // => bar(%Z)
s('bar(%s, %s)'.15px);               // => bar(15px, null)
Copy the code

Detect the % string operator for consistency.

operate(op, left, right)

Performs the given op on the left and right operation objects.

op = '+'
operate(op, 15.5)                    / / = > 20
Copy the code

length([expr])

The parenthesis expression acts as a tuple, and the length() method returns the length of the expression.

length((1 2 3 4))                    / / = > 4
length((1 2))                        / / = > 2
length((1))                          / / = > 1
length(())                           / / = > 0
length(1 2 3)                        / / = > 3
length(1)                            / / = > 1
length(a)                             / / = > 0
Copy the code

warn(msg)

Use the given error warning without exiting.

warn("oh noes!")
error(msg)                            MSG exits with the given error.
Copy the code

add(a, b)

  unless a is a 'unit' and b is a 'unit'
    error('add() expects units')
  a + b
Copy the code

last(expr)

Returns the last value of the given expr.

nums = 1 2 3
last(nums)
last(1 2 3)                           / / = > 3

list = (one 1) (two 2) (three 3)
last(list)                            // => (three 3)
Copy the code

p(expr)

Check the given EXPR.

fonts = Arial, sans-serif
p('test')
p(123)
p((1 2 3))
p(fonts)
p(#fff)
p(rgba(0.0.0.0.2))
add(a, b)
  a + b
// p(add)
inspect: "test"
inspect: 123
inspect: 1 2 3
inspect: Arial, sans-serif
inspect: #fff
inspect: rgba(0.0.0.0.2)
inspect: add(a, b)
Copy the code

opposite-position(positions)

Returns the opposite of a given position.

opposite-position(right)                      // => left
opposite-position(top left)                   // => bottom right
opposite-position('top' 'left')               // => bottom right
Copy the code

image-size(path)

Returns the width and height of the specified path image. The way to find paths up is the same as @import.

width(img)
  return image-size(img)[0]

height(img)
  return image-size(img)[1]

image-size('tux.png')                         // => 405px 250px
image-size('tux.png')[0]= =width('tux.png')  // => true
Copy the code

add-property(name, expr)

Add the attribute name to the nearest block domain using the given expR.

Such as:

something(a)
  add-property('bar'.1 2 3)
  s('bar')

body
  foo: something()
Copy the code

Results:

body {
  bar: 1 2 3;
  foo: bar;
}
Copy the code

Next comes the magic current-property local variable, which is automatically supplied to the function body and contains an expression for the current property name and value. For example, checking this local variable with p() yields:

p(current-property)                         // => "foo" (foo __CALL__ bar baz)
p(current-property[0])                      // => "foo"
p(current-property[1])                      // => foo __CALL__ bar baz
Copy the code

Using current-property takes the example a step further, duplicating the property with a new value and ensuring that the condition of the functionality is only used in the property value.

something(n)
  if current-property
    add-property(current-property[0], s('-webkit-something(%s)', n))
    add-property(current-property[0], s('-moz-something(%s)', n))
    s('something(%s)', n)
  else
    error('something() must be used within a property')

body {
  foo: something(15px) bar;
}
Copy the code

For:

body {
  foo: -webkit-something(15px);
  foo: -moz-something(15px);
  foo: something(15px) bar;
}
Copy the code

Undefined method

Undefined method a literal output. For example, we can call rgba-stop(50%, # FFF) in CSS and it will display as you expect. In this example we simply define the method stop(), which returns the literal rgba-stop() call.

stop(pos, rgba)
  rgba-stop(pos, rgba)

stop(50%, orange)                           // => rgba-stop(50%, #ffa500)
Copy the code