Meadows of wild horses

Blog...

CoffeeScript Tutorial

| Comments

coffeescript.org

Functions

함수는 ->로 정의 합니다.

example-01.coffee
1
2
3
4
square = (x) -> x * x
cube   = (x) -> square(x) * x

alert cube(5)
example-01.js
1
2
3
4
5
6
7
8
9
10
var cube, square;

square = function(x) {
  return x * x;
};

cube = function(x) {
  return square(x) * x;
}
alert(cube(5));

함수 생성시 인자를 생성및 전달 할수 있습니다.

example-02.coffee
1
2
3
fill = (container, liquid = "coffee") ->
  "Filling the #{container} with #{liquid}…"
alert fill("cup")
example-2.js
1
2
3
4
5
6
7
8
9
10
var fill;

fill = function(container, liquid) {
  if (liquid == null) {
    liquid = "coffee";
  }
  return "Finling the " + container + " with " + liquid + "...";
};

alert(fill("cup"));

Objects and Arrays

Array는 ‘,’로 인자를 구분 하며 YAML과 같이 개행 문자로도 구분 가능 합니다.

example-03.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
song = ["do", "re", "mi", "fa", "so"]

singers = {Jagger: "Rock", Elvis: "Roll"}

bitlist = [
  1, 0, 0
  0, 0, 1
  1, 1, 0
]

kids =
  brother:
    name: "Max"
    age: 11
  sister:
    name: "Ida"
    age: 9
alert song.join("…")
example-03.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var bitlist, kids, singers, song;

song = ["do", "re", "mi", "fa", "so"]
singers = {
  Jagger: "Rokcer",
  Elvis: "Roll"
};

bitlist = [1, 0, 1, 0, 0, 1, 1 , 1, 0];

kids = {
  brother: {
    name: "Max",
    age: 11
  },
  sister: {
    name: "Ida",
    age: 9
  }
};
alert(song.join(" … "));
example-03-01.coffee
1
2
$('.account').attr class: 'active'
log object.class

Lexical Scoping and Variable Safety(지역변수)

changeNumbers = ->안에 outer값은 외부의 outer의 영향을 받지 않습니다. alert outeralert inner의 값은 각 110입니다.

example-04.coffee
1
2
3
4
5
6
7
outer = 1
changeNumbers = ->
  inner = -1
  outer = 10
inner = changeNumbers()

alert inner

If, Else, Unless, and Conditional Assignment

singing값이 참일때 mood = greatlyImproved를 리턴 합니다.

example-05-01.coffee
1
mood = greatlyImproved if singing

happyknowIt두개의 값이 참일때와 아닐때를 분류 합니다.

example-05-02.coffee
1
2
3
4
5
if happy and knowIt
  clapsHands()
  chaChaCha()
else
  showIt()

다른 언어의 3항 연산자와 같이 동작 합니다. friday값이 참일때는 sue 아닐때는 jill입니다.

example-05-03.coffee
1
date = if friday then sue else jill

Splats…

(점3개) Array를 잘라 낼수 있습니다. awardMedals contenders… contenders를 분할하여 awardMedals에 정의 됩니다. 여러개의 값이 있고 3개의 변수가 정의 되어 있을때 분할된 첫번째와 두번째는 개별 인자로 정의 되고 나머지 변수에 남은 Array값이 저장 됩니다.

example-06.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
gold = silver = rest = "unknown"

awardMedals = (first, second, others…) ->
  gold   = first
  silver = second
  rest   = others

contenders = [
  "Michael Phelps"
  "Liu Xiang"
  "Yao Ming"
  "Allyson Felix"
  "Shawn Johnson"
  "Roman Sebrle"
  "Guo Jingjing"
  "Tyson Gay"
  "Asafa Powell"
  "Usain Bolt"
]

awardMedals contenders

alert "Gold: " + gold
alert "Silver: " + siliver
alert "the Field: " + rest

Loops and Comprehensions

Array의 값은 in으로 가져올수 있습니다 이를 food에 정의 하고 eat함수에 인자로 전달 합니다. eat food.js에서 eat(food); 변환됩니다.

example-07.coffee
1
eat food for food in ['tast', 'cheese', 'wine']

Array값을 받을 변수 dish와 증가값 i정의 합니다. i0에서 1씩 증가 합니다.

example-07-01.coffee
1
2
courses = ['greens', 'caviar', 'truffles', 'roast', 'cake']
  menu i + 1, dish for dish, i in courses

by는 반복문 실행시 1개씩이 아닌 2개씩 건너뜁니다.

example-07-011.coffee
1
evens = (x for x in [0..10] by 2)

반복문과 비교문을 같이 정의 합니다. isntfor문 안에서 if !=으로 변환 됩니다.

example-07-02.coffee
1
2
foods = ['broccoli', 'spinach', 'chocolate']
eat food for food in foods when food isnt 'chocolate'

name의 길이가 5 미만인 값만을 반환 받습니다.

example-07-03.coffee
1
shortNames = (name for name in list when name.length < 5)

10..1값들은 Array에 push해 반환 합니다. countdown값은 10,9,8,7,6,5….1값이 됩니다.

example-08.coffee
1
countdown = (num for num in [10..1])

ofkey: value를 반환 합니다. yearsOld의 key, value가 chile``age로 정의 됩니다. ages는 문장 3개를 받습니다.(push)

example-09.coffee
1
2
3
4
yearsOld = max: 10, ida: 9, tim: 11

ages = for child, age of yearOld
  "#{child} is #{age}"

whileuntil을 사용 할수 있습니다.

example-10.coffee
1
2
3
4
# Econ 101
if this.studyingEconomics
  buy() while supply > demand
  sell() until supply > demand
example-10-01.coffee
1
2
3
4
5
6
7
`num`값이 `0`될때까지 횟수 만큼 문자열을 반환 합니다.

# Nursey Rhyme
num = 6
lyrics = while num -= 1
  "#{num} little monkeys, jumping on the bed.
  One fell out and bumped his head."

coffeescript do의 대한 설명

When using a JavaScript loop to generate functions,
it's common to insert a closure wrapper
in order to ensure that loop variables are closed over,
and all the generated functions don't just share the final values.
CoffeeScript provides the `do` keyword,
which immediately invokes a passed function, forwarding any arguments.     
example-11.coffee
1
2
3
4
for filename in list
  do (filename) ->
    fs.readFile filename, (err, contents) ->
      compile filename, contents.toString()

Array Slicing and Splicing with Ranges

start값은 1, 2, 3값을 반환 합니다.

example-12.coffee
1
2
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
start = numbers[0..2]

...6보다 작은값(6까지가 아님)까지 입니다. 반환값은 4,5,6입니다.

example-12-01.coffee
1
middle = numbers[36]

6번째 자릿수 부터 가져 옵니다. 반환값은 7,8,9입니다.

example-12-02.coffee
1
end = numbers[6..]

0번째 부터 이므로 모든 값을 가져옵니다.

example-12-03.coffee
1
copy = numbers[..]

numvers[3..6] 자리에 값과 변경 합니다.

example-13.coffee
1
2
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
numbers[3..6] = [-3, -4, -5, -6]

Everything is an Expression (at least, as much as possible)

if/else if/else 구문 입니다. 비교를 2번 할수 있습니다. if~then~else는 3항 연산자와 같이 쓸수 있습니다.

example-14.coffee
1
2
3
4
5
6
7
8
9
grade = (student) ->
  if student.excellentWork
    "A+"
  else if student.okayStuff
    if student.triedHard then "B" else "B-"
  else
    "C"

eldest = if 24 > 21 then "Liz" else "Ike"

변수 선언과 동시에 계산이 가능 합니다.

example-15.coffee
1
six = (one = 1) + (two = 2) + (three = 3)

window의 값을 10개 분할합니다.(slice)

example-16.coffee
1
globals = (name for name of window)[010]

try/catch

try계산 하고 error가 catch되면 try된 값이 아닌 catch값이 리턴 됩니다.

example-17.coffee
1
2
3
4
5
6
alert(
  try
    nonexistent / underfined
  catch error
    "And the error is … ${error}"
)

Operators and Aliases

CoffeeScript    |     JavaScript
    is          |        ===
   isnt         |        !==
    not         |        !
    and         |        &&
    or          |        ||
true, yes, on   |       true
false, no, off  |       false
   @, this      |       this
    of          |       in
    in          |   no JS equivalent

if (ignition === true)와 같습니다.

example-18-01.coffee
1
launch() if ignition is on

(band !== Spinaltap)과 같습니다.

example-18-02.coffee
1
volume = 10 if band isnt SpinalTap

unless와 중복 되어 if ( answer !== false)`와 같습니다.

example-18-03.coffee
1
letTheWildRumpusBegin() unless answer is no

if (car.speed < limit)일때 실행과 같습니다.

example-18-04.coffee
1
if car.speed < limit then accelerate()

if (pick === 47 || pick === 92 || pick == 13)과 같습니다.

example-18-05.coffee
1
winner = yes if pick in [47, 92, 13]

print(inspect("My name is this.name));와 같습니다. @.js의 this를 의미 합니다.

example-18-06.coffee
1
print inspect "My name is #{@name}"

The Existential Operator

coffeescript에서 ?undefinednull값인지 비교 합니다. speed ?= 15speednull인지 검사 합니다.

example-19.coffee
1
2
3
4
solipsism = true if mind? and no world?

speed = 0
speed ?= 15

yetiundefiendnull이 아닐 경우 yeti값을 반환하고 아니라면 bear 를 반환 합니다. 3항 연산자와 같은 형식 입니다.

example-19-01.coffee
1
footprints = yeti ? "bear"

coffeescript의 ?..

The accessor variant of the existential operator ?.
can be used to soak up null references in a chain of properties.
Use it instead of the dot accessor . in cases where the base value may be null or undefined.
If all of the properties exist then you'll get the expected result,
 if the chain is broken, undefined is returned instead of the TypeError that would be raised otherwise. 
example-20.coffee
1
zip = lottery.drawWinner?().address?.zipcode

Classes, Inheritance, and Super

class를 선언하고 불러 올수 있습니다.

new [class name]을 선언해서 class를 사용 합니다. 사용된 SnakeHorse에서 extends Animal을 사용 하였으므로 class Animal을 사용 합니다.

example-21.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Animal
  constructor: (@name) ->

  move: (meters) =>
    alert @name + " moved #{meters}m."

class Snake extends Animal
  move: ->
    alert "Slithering…"
    super 5

class Horse extends Animal
    move: ->
      alert "Galloping…"
      super 45

sam = new Snake "Sammy the Python"
tam = new Horse "Tommy the Palomino"

sam.move()
tom.move()

prototype ‘::’

::.prototype.의 줄임 표현 입니다. String::dasherizeString.prototype.dasherize로 변환 됩니다.

example-22.coffee
1
2
String::dasherize = ->
  this.replace /_/g, "-"

Destructuring Assignment

선언된 두개의 값을 교환 합니다.

example-22.coffee
1
2
3
4
theBait = 1000
theSwitch = 0

[theBait, TheSwitch] = [theSwitch, theBait]

여러값의 반환

리턴 값으로 locatioin, 72, Mostly Sunny값 3개를 한번에 반환 합니다.

example-23.coffee
1
2
3
4
weatherReport = (location) ->
  [location, 72, "Mostly Sunny"]

[city, temp, forecast] = weatherReport "Berkeley, CA"

object의 반환

futurists object 값을 반환 합니다.

example-24.coffee
1
2
3
4
5
6
7
8
9
10
futurists =
  sculptor: "Umberto Boccioni"
  painter: "Vladimir Burliuk"
  poet:
    name: "F.T Marinetti"
    address: [
      "Via Roma 42R"
      "Bellagio, Italy 22021"
    ]
{poet: {name, address: [street, city]}} = futurists

split의 반환 값으로 open, contents... close 3군데로 나누어 받습니다. contents...값은 마지막 값 하나를 제외 하고 모든 값을 받습니다.

example-25.coffee
1
2
3
tag = "<impossible>"

[open, contents, close] = tag.split("")

Function binding

->함수 선언전의 (customer, cart)처럼 전달 인자를 정의 해줄수 있습니다.

example-26.coffee
1
2
3
4
5
6
Account = (customer, cart) ->
  @customer = customer
  @cart = cart

  $('.shopping_cart').bind 'click', (event) =>
    @customer.purchase @cart

Embedded JavaScript

coffeescript 안에서 JavaScript 사용하기 위해서는 backticks가 필요 합니다.

example-27.coffee
1
2
3
hi = `function() {
  return [document.title, "Hello JavaScript"].join(": ");
}`

Switch/When/Else

day값을 when으로 비교 하고 when에 해당 하지 않으면 else를 실행 합니다.

example-28.coffee
1
2
3
4
5
6
7
8
9
10
switch day
  when "Mon" then go work
  when "Tue" then go relax
  when "Thu" then go iceFishing
  when "Fri", "Sat"
    if day is bingoDay
      go bingo
      go dancing
  when "Sun" then go church
  else go work

Try/Catch/Finally

try 시도를 하고 결과 같으로 catach와 비교 하여 아니면 finally를 실행 합니다.

example-29.coffee
1
2
3
4
5
6
7
try
  allHellBreaksLoose()
  catsAndDogsLivingTogether()
catch error
  print error
finally
  cleanUp()

Chained Comparisons

cholesterol값이 200보다 작거나 60보다 큰지 검사합니다.

example-30.coffee
1
2
3
cholesterol = 127

healthy = 200 > cholesterol > 60

String Interpolation, Block Strings, and Block Comments

#{}은 문자열 보간입니다. #{ number / number}사용시 문자로 취급합니다.

example-31.coffee
1
2
3
4
quthor = "Wittgenstein"
quote  = "A picture is a fact. -- #{ author }"

sentence = "#{ 22/ 7 } is a decent approximation of ㅠ"

coffeescript 는 여러 문장의 개행을 인식 하지 않습니다.

example.32
1
2
3
4
5
6
mobyDick = "Call me Ishmael. Some years ago --
  never mind how long precisely -- having little
  or no money in my purse, and nothing particular
  to interset me on shore, I thought I would sail
  about a little and see the watery part of the
  world…"

Javascript 변환시 개행문자를 추가 하려면 """사용해 주어야 합니다.

example-33.coffee
1
2
3
4
5
html = """
  <strong>
    cup of coffeescript
  </strong>
  """

coffeescript의 여러줄 주석 입니다.

example-34.coffee
1
2
3
4
###
CoffeeScript Compiler v1.4.0
Released under the MIT License
###

Block Regular Expressions

OPERATOR = /// ^ (
  ?:[-=]>
   | [-+*/%<>&|^!?=]=
   | >>>=?
   |([-+:])\1
   |([&|<>])\2=?
   |\?\.
   |\.{2,3}
) ///

CoffeeScript Style Guide

CoffeeScript의 문법 사용법을 알려주는 사이트 주소 입니다. CoffeeScript Style Guide

Js2coffee

| Comments

Javascript -> CoffeeScript

login.js

기존 login.js

1
2
3
4
5
// login.js

$(document).ready(function) {
  $("#login_username").focus();
});

login.coffee 작성

1
2
3
 # login.coffee
$ ->
  $("#login_username").focus()

컴파일된 login.js

1
2
3
4
5
6
// login.js
(functioni () {
  $(function() {
    return $("#login_username").focus();
  });
}).call(this);

list.js

기존 list.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
$(document).ready(function () {
  $('#head_checkbox').click(function() {
    //find all checkboxes
    var cbs = $("input:checkbox");
    //화면상의 모든 Checkbox 를 찾아서 Head Checkbox 상태와 동기화 합니다. (대장이 체크면 쫄도 모두다 채크)
    for (var i = 0; i < cbs.length; i++) {
          if (cbs[i].type == "checkbox") {
            cbs[i].checked = $(this).is(':checked');
          }
    }
  });

  $('#do_delete').click(function() {
    var selected_charges = [];

    $('#charge_list tr').filter(':has(:checkbox:checked)').each(function(){
      if($(this).attr('id') !== undefined)
        selected_charges.push($(this).attr('id'))
    });

    location.href = '/list/delete/' + selected_charges;
  });

  $('#do_approval').click(function() {
    var selected_charges = [];

    $('#charge_list tr').filter(':has(:checkbox:checked)').each(function(){
      if($(this).attr('id') !== undefined)
        selected_charges.push($(this).attr('id'))
    });

    location.href = '/list/approval/' + selected_charges;
  });

  $('#do_refuse').click(function() {
    var selected_charges = [];

    $('#charge_list tr').filter(':has(:checkbox:checked)').each(function(){
      if($(this).attr('id') !== undefined)
        selected_charges.push($(this).attr('id'))
    });

    location.href = '/list/refuse/' + selected_charges;
  });
  $('#do_deposit').click(function() {
    var selected_charges = [];

    $('#charge_list tr').filter(':has(:checkbox:checked)').each(function(){
      if($(this).attr('id') !== undefined)
        selected_charges.push($(this).attr('id'))
    });

    location.href = '/deposit/approval/' + selected_charges;
  });

  $('#do_export').click(function() {
    var selected_charges = [];

    $('#charge_list tr').filter(':has(:checkbox:checked)').each(function(){
      if($(this).attr('id') !== undefined)
        selected_charges.push($(this).attr('id'))
    });

    location.href = '/deposit/export/' + selected_charges;
  });

  $('#do_cancel').click(function() {
    var selected_charges = [];

    $('#charge_list tr').filter(':has(:checkbox:checked)').each(function(){
      if($(this).attr('id') !== undefined)
        selected_charges.push($(this).attr('id'))
    });

    location.href = '/deposit/cancel/' + selected_charges;
  });

  window.prettyPrint && prettyPrint();
  ${'#start_date'}.datepicker({
    format: 'yyyy-mm-dd'
  });
  window.prettyPrint && prettyPrint();
  ${'#end_date').datepicker({
    format: 'yyyy-mm-dd'
  });
});

기존 코드를 .coffee 파일로 수정 한것입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ ->
  $('#head_checkobx').click ->
    flag = $(@).is(':checked')
    $(':checkbox').each ->
      if flag then $(@).attr('checked', 'checked')
      else $(@).removeAttr('checked')

  $('.btn').click ->
    select_id = $(@).attr("id").substring(3)
    selected_charges = []

    $('#charge_list tr').filter(':has(:checkbox:checked)').each ->
      if $(@).attr('id') isnt undefined
        selected_charges.push($(@).attr('id'))
    location.href = "/list/#{select_id}/#{selected_charges}"

  window.prettyPrint and prettyPrint()
  $('#start_date, #end_date').datepicker
    format: 'yyyy-mm-dd'

head_checkbox

#head_checkbox는 최상의 checkbox 컨트롤러 이며 하위 checkbox 들을 조정 합니다. 체크시 하위 모든 checkbox가 모두 클릭 되며 미클릭시 하위 checkbox 또한 미클릭으로 전환 합니다.

1
2
3
4
5
6
7
8
9
10
$('#head_checkbox').click(function() {
    //find all checkboxes
    var cbs = $("input:checkbox");
    //화면상의 모든 Checkbox 를 찾아서 Head Checkbox 상태와 동기화 합니다. (대장이 체크면 쫄도 모두다 채크)
    for (var i = 0; i < cbs.length; i++) {
          if (cbs[i].type == "checkbox") {
            cbs[i].checked = $(this).is(':checked');
          }
    }
  });

수정된 head_checkbox 코드

1
2
3
4
5
6
$ ->
  $('#head_checkbox').click ->
    flag = $(@).is(':checked')
    $(':checkbox').each ->
      if flag then $(@).attr('checked', 'checked')
      else $(@).removeAttr('checked')

.btn 클릭

#do_xxx클릭시 발생되는 코드 입니다. 코드 중복상태가 많은 기존의 .js 입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$('#do_delete').click(function() {
    var selected_charges = [];

    $('#charge_list tr').filter(':has(:checkbox:checked)').each(function(){
      if($(this).attr('id') !== undefined)
        selected_charges.push($(this).attr('id'))
    });

    location.href = '/list/delete/' + selected_charges;
  });
.
$('#do_approval').
$('#do_change')

$('#do_cancel').click(function() {
    var selected_charges = [];

    $('#charge_list tr').filter(':has(:checkbox:checked)').each(function(){
      if($(this).attr('id') !== undefined)
        selected_charges.push($(this).attr('id'))
    });

    location.href = '/deposit/cancel/' + selected_charges;
  });

#do_xxx클릭시 개별적으로 선언 된것을 coffee로 수정 하면서 .btn클릭 이벤트 발생시 아이디의 #do_제외한 문자열을 추출 하여 필요한 동작을 완성 하였습니다.

1
2
3
4
5
6
7
8
$('.btn').click ->
  select_id = $(@).attr("id").substring(3)
  selected_charges = []

  $('#charge_list tr').filter(':has(:checkbox:checked)').each ->
    if $(@).attr('id') isnt undefined
      selected_charges.push($(@)).attr('id'))
  location.href = "/deposit/${select_id}/${selected_charges}"

반복 코드 중첩

기존에 반복 되던 코드 .js

1
2
3
4
5
6
7
8
window.prettyPrint && prettyPrint();
${'#start_date'}.datepicker({
  format: 'yyyy-mm-dd'
});
window.prettyPrint && prettyPrint();
${'#end_date').datepicker({
  format: 'yyyy-mm-dd'
});

중첩 시켜 짧게 만드는 .coffee

1
2
window.prettyPrint && prettyPrint();
$('#start_date, #end_date').datepicker

list_write.js

기존 list_write.js

1
2
3
$(document).ready(functoiin() {
  $('#title').focus();
});

수정 list_write.coffee

1
2
$ ->
  $('#title').focus()

write_validation.js

기존 write_validation.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$(document).ready(function() {
 $('#w_form').validate({
   rules: {
     title: {
       required: true,
     },
     amount: {
       required: true,
       number: true
     }
   },
  messages: {
    title: {
        required: "제목을 입력해 주세요"
    },
    amount: {
        required: "금액을 입력해 주세요",
        number: "숫자만 입력해 주세요"
    }
  }
 });
});

수정 write_validatioin.coffee

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ ->
  $('#w_form').validation
    rules:
      title:
        required: true
      amount:
        required: true
        number: true
    messages:
      title:
        required: "제목을 입력해 주세요"
      amount:
        required: "금액을 입력해 주세요"
        number: "숫자만 입력해 주세요"

Perl

| Comments

해당 되는 파일의 이름을 찾아 그 안에서 정규 표현식에 해당 되는 문자열을 치환 해주는 기능

1
$ perl -pi -e 's/scripts/scripts\.coffee/g' `find . -name '*.tt'`

Sass

| Comments

CSS의 확장 Sass

Nested Rules

.scss 중첩 규칙 - 1

example-01.scss
1
2
3
4
5
6
7
8
9
#main p {
  color: #00ff00;
  width: 97%;

  .redbox {
    boackground-color: #ff0000;
    color: #0000;
  }
}

컴파일된 .css #main p.redbox가 상속 받으면 2칸 들여 쓰기 됩니다.

example-01.css
1
2
3
4
5
6
#main p {
  color: #00ff00;
  wdth: 97%; }
  #main p .redbox {
    background-color: #ff0000;
    color: #000000; }

.scss 중첩 규칙 - 2

모든 selector에 #main이 상속 됩니다.

example-02.scss
1
2
3
4
5
6
7
8
9
#main {
  width: 97%;

  p, div {
    font-size: 2em;
    a { font-weight: bold; }
  }
  pre { font-size: 3em; }
}
example-02.css
1
2
3
4
5
6
7
8
#mian {
  width: 97%; }
  #mian p, #main div {
    font-size: 2em; }
    #mian p a, #main div a {
      font-weight: bold; }
  #main pre {
    font-size: 3em; }

부모 셀렉터의 상속자: &

&를 사용함으로서 부모 셀렉터를 상속 받을수 있습니다.

example-03.scss
1
2
3
4
5
6
a {
  font-weight: bold;
  text-decoration: none;
  &:hover { text-decoration: underline; }
  body.firefox & { font-weight: normal; }
}

&은 부모 a를 상속 받습니다.

example-03.css
1
2
3
4
5
6
7
a {
  font-weight: bold;
  text-decoration: none; }
  a:hover {
    text-decoration: underline; }
  body.firefox a {
    font-weight: normal; }

상속자의 상위 상속자도 포함 됩니다.

example-04.scss
1
2
3
4
5
6
7
#main {
  color: black;
  a {
    font-weight: bold;
    &:hover { color: red; }
  }
}

최상의 부모인 #main을 포함 합니다.

example-04.css
1
2
3
4
5
6
#main {
  color: black; }
  #main a {
    font-weight: bold; }
      #main a:hover {
  color: red; }

Nested Properties

태그의 속성도 상속 합니다.

example-05.scss
1
2
3
4
5
6
7
.funky {
  font: {
    family: fantasy;
    size: 30em;
    weight: bold;
  }
}

font의 속성들이 상속 됩니다.

example-05.css
1
2
3
4
.funky {
  font-family: fantasy;
  font-szie: 30em;
  font-weight: bold; }

개별 태그와 속성 상속 예 입니다.

example-06.scss
1
2
3
4
5
6
7
.funky {
  font: 2px/3px {
    family: fantasy;
    size: 30em;
    weight: bold;
  }
}

태그는 따로 선언 되었습니다.

example-06.css
1
2
3
4
5
.funky {
  font: 2px/3px;
    font-family: fantasy;
    font-size: 30em;
    font-weight: bold; }

주석: /* */ and //

//한줄 주석으로 변환시 .css에 표시 되지않습니다. /* */ 다중 주석 문으로 .css변환시에도 남아 있습니다.

example-07.scss
1
2
3
4
5
/* multiple line
    is not delete in css */
body { color: black; }
// one line is delete in css
a { color: green; }
example-07.css
1
2
3
4
/* multiple line
    is not delete in css */
body { color: black; }
a { color: green; }

변수: $

변수 선언 기호는 $입니다.

example-08.scss
1
2
3
4
$width: 5em;
#main {
  width: $width;
}

선언된 $width: 5em값이 적용 됩니다.

example-08.css
1
2
3
#main {
  width: 5em;
}

문자열

변수 선언후 문자열에 #{$string}을 통해서 사용 할수 있습니다.

example-09.scss
1
2
3
4
5
6
@mixin firefox-message($selector) {
  body.firefox #{$selector}:before {
    content: "Hi, Firefox users!";
  }
}
@include firefox-message(".header");

$selector에 인자로 .header을 받고 #{$selector}값에 대입 합니다.

example-09.css
1
2
body.firefox .header:before {
  content: "Hi, Firefox users!"; }

숫자 연산

in와 pt를 같이 사용하면 in로 변환되어 계산 됩니다.

example-10.scss
1
2
3
p {
  width: 1in + 8pt;
}
example-10.css
1
2
p {
  width: 1.111in }

나누기 와 /

margin-left 처럼 다른 인수와 연산을 하지 않으면 .css변환시 표기대로 변환 됩니다.

example-11.scss
1
2
3
4
5
6
7
p {
  font: 10px/8px;
  $width: 1000px;
  width: $width/2;
  height: (500px/2);
  margin-left: 5px + 8px/2px;
}

font의 값은 연산하지 않습니다.

example-11.css
1
2
3
4
5
6
p {
  font: 10px/8px;
  width: 500px;
  height: 250px;
  margin-left: 9px;
}

변수에 할당하여 연산할수도 있습니다.

example-12.scss
1
2
3
4
5
p {
  $font-size: 12px;
  $line-height: 30px;
  font: #{$font-size}/#{$line-height};
}
example-12.css
1
2
p {
  font: 12px/30px; }

Color 연산

Color의 덧셈 입니다.

example-13.scss
1
2
3
p {
  color: #010203 + #040506;
}
example-13.css
1
2
p {
  color: #050709; }

Color의 곱셈 입니다.

example-14.scss
1
2
3
p {
  color: #010203 * 2;
}
example-14.css
1
2
p {
  color: #020406; }

rgba 덧셈

최소 값은 0이며 양측 덧셈 최대값은 255 입니다. 투명도가 동일값(0.75) 이어야 계산이 됩니다.

example-15.scss
1
2
3
p {
  color: rgba(255, 0, 0, 0.75) + rgba(0, 255, 0, 0.75);
}
example-15.css
1
2
p {
  color: rgba(255, 255, 0, 0.75); }

opacify 투명도값인 0.5 + 0.3 으로 계산 합니다. transparentize0.5의 값을 0.25로 변경합니다.

example-16.scss
1
2
3
4
5
$translucent-red: rgba(255, 0, 0, 0.5);
p {
  color: opacify($translucent-red, 0.3);
  background-color: transparentize($translucent-red, 0.25);
}
example-16.css
1
2
3
p {
  color: rgba(255, 0, 0, 0.8);
  background-color: rgba(255, 0, 0, 0.25); }

문자열 연산

문자열의 덧셈

일반적인 문자열 덧셈

example-17.scss
1
2
3
p {
  cursor: e + -resize;
}
example-17.css
1
2
p {
  cursor: e-resize; }

공백을 포함한 문자열의 덧셈 ""로 감싸주게 됩니다.

example-18.scss
1
2
3
4
p:before {
  content: "Foo " + Bar;
  font-family: sans- + "serif";
}
example-18.css
1
2
3
p:before {
  content: "Foo Bar";
  font-family: sans-serif; }

px값과 auto 인자가 있을시 ( ) 없이도 px값 만 계산 합니다.

example-19.scss
1
2
3
p {
  margin: 3px + 4px auto;
}
example-19.css
1
2
p {
  margin: 7px auto; }

문자열 내에서 덧셈이 가능합니다.

example-20.scss
1
2
3
p:before {
  content: "I ate #{5 + 10} pies!";
}
example-20.css
1
2
p:before {
  content: "I ate 15 pies!"; }

변수 값이 null일시 무시 합니다.

example-21.scss
1
2
3
4
$value: null;
  p:before {
  content: "I ate #{$value} pies!";
}
example-21.css
1
2
p:before {
  content: "I ate pies!"; }

Parentheses(괄호)

( )우선 순위로 계산 합니다.

example-22.scss
1
2
3
p {
  width: 1em + (2em * 3);
}
example-22.css
1
2
3
p {
  width: 7em;
}

Functions(함수)

hsl ($hue, $saturation, $lightness) 괄호의 값은 (색깔, 채도, 밝기)을 뜻합니다.

example-23.scss
1
2
3
p {
  color: hsl(0, 100%, 50%);
}
example-23.css
1
2
p {
  color: red; }

Interpolation: #{} (보간법)

문자 보간 하는 방법 입니다. $namefoo$attrborder#{$name}, #{$attr}을 사용해 보간 합니다.

example-24.scss
1
2
3
4
5
$name: foo;
$attr: border;
p.#{$name} {
  #{$attr}-color: blue;
}
example-24.css
1
2
3
p.foo {
  border-color: blue;
}

px값도 보간할수 있습니다.

example-25.scss
1
2
3
4
5
p {
  $font-size: 12px;
  $line-height: 30px;
  font: #{$font-size} / #{$line-height};
}
example-25.css
1
p { font: 12px / 30px; }

Variable Defaults: !default (기본 변수)

$content값이 참인지 분별하여 거짓이면 Second content?값을 부여 합니다. 참이므로 $contentFirst..가 됩니다. $new_content는 거짓 이므로 First time…을 출력 합니다.

example-26.scss
1
2
3
4
5
6
7
8
$content: "First content";
$content: "Second content?" !default;
$new_content: "First time reference" !default;

#main {
  ccontent: $content;
  new-content: $new_content;
}
example-26.css
1
2
3
4
#main {
  content: "First content";
  new-content: "First time reference";
}

$content의 값이 null이므로 !default가 동작 합니다.

example-27.scss
1
2
3
4
5
6
$content: null;
$content: "Non-null content" !default;

#main {
  content: $content;
}
example-27.css
1
2
3
#main {
  content: "Non-null content";
}

@-Rules and Directives

import

.sass, .scss 파일을 @import해서 작업 할수 있고 .css파일에 출력이 가능 합니다.

example-28.scss
1
2
@import "foo.scss";  //  아래와 같은 의미 입니다.
@import "foo";       //  위와 같은 의미 입니다.

.scss, .sass외에도 @import 가능합니다.

example-28-01.scss
1
2
3
4
@import "foo.css";
@import "foo" screen;
@import "http://foo.com/bar";
@import url(foo);
example-28-01.css
1
2
3
4
@import "foo.css";
@import "foo" screen;
@import "http://foo.com/bar";
@import url(foo);

multiple import(다중 호출)

여러개의 파일을 한번에 @import할수 있습니다.

example.scss
1
@import "rounded-corners", "text-shadow";

@import interpolation #{}

interpolation is only for CSS imports. As such, it only works with url() imports.

example.scss
1
2
$family: unquote("Droid-Sans");
@import url("http://fonts.googleapis.com/css?family=\#{$family}");

Partials

colors@import를 하게 되면 기본적으로 .css 파일이 없는 상태에서 _color.scss파일을 @import하게 되고 이도 없으면 비슷한 color.scss파일을 import합니다.

example.scss
1
@import "colors";

Nested @import

{ }에서 @import를 하게 되면 .example을 불러 옵니다.

\_example.scss
1
2
3
.example {
  color: red;
}
example-29-01.scss
1
2
3
#main {
  @import: "example";
}
example-29-01.css
1
2
3
#main .example {
  color: red;
}

@media

상단의 .sidebar를 상속 해서 손쉽게 @media옵션과 아닌 옵션을 따로 선언 할수 있습니다.

example.scss
1
2
3
4
5
6
.sidebar {
  width: 300px;
  @media screen and (orientation: landscape) {
    width: 500px;
  }
}
example.css
1
2
3
4
5
.sidebar {
  width: 300px; }
  @media screen and (orientation: landscape) {
    .sidebar {
    width: 500px; } }

@media안에 @media를 합칠수 있습니다.

example.scss
1
2
3
4
5
6
7
@media screen {
  .sidebar {
    @media (orientation: landscape) {
      width: 500px;
    }
  }
}
example.css
1
2
3
4
@media screen and (orientation: landscape) {
  .sidebar {
    width: 500px; } }
}

@media에 SassScript 문법인 #{}를 사용 할수있습니다.

example.scss
1
2
3
4
5
6
7
8
$media: screen;
$feature: -webkit-min-device-pixel-ratio;
$value: 1.5;

@media #{$media} and ($feature: $value) {
  .sidebar {
    width: 500px; } }
}
example.css
1
2
3
4
@media screen and (-webkit-min-device-pixel-ratio: 1.5) {
  .sidebar {
    width: 500px; } }
}

@extend

markup.html
1
2
3
<div class="error seriousError">
  Oh no! You've been hacked!
</div>

.error, .seriousError이 개별적으로 선언 되어 있고 두개의 속성을 모두 가지기 위해서는 클래스명을 두개다 선언해 주어야 합니다.

error.css
1
2
3
4
5
6
7
.error {
  border: 1px #f00;
  background-color: #fdd;
}
.seriousError {
  border-width: 3px;
}

다음은 .seriousError만 선언 하여도 .error가지 같이 적용 될수 있도록 수정한 코드 입니다.

error.scss
1
2
3
4
5
6
7
8
.error {
  border: 1px #f00;
  background-color: #fdd;
}
.seriousError {
  @extend .error;
  border-width: 3px;
}
markup.html
1
2
3
4
<div class="error seriousError">
  Oh no! You've been hacked!
</div>
<div class="seriousError intrusion"></div>

다른 스타일 추가

example.scss
1
2
3
.error.intrusion {
  background-image: url("/image/hacked.png");
}

사용법

error.intrusion을 정의해 주면 @extend .error에 같이 적용되어 .css안에 .seriousError또한 생성 됩니다.

example.scss
1
2
3
4
5
6
7
8
9
10
11
.error {
  border: 1px #f00;
  background-color: #fdd;
}
.error.intrusion {
  background-image: url("/image/hacked.png");
}
.seriousError {
  @extend .error;
  border-width: 3px;
}
example.css
1
2
3
4
5
6
7
8
9
10
.error, .seriousError {
  border: 1px #f00;
  background-color: #fdd;
}
.error.intrusion, .seriousError.intrusion {
  background-image: url("/image/hacked.png");
}
.seriousError {
  border-width: 3px;
}

Extending Complex Selectors

Class selectors aren’t the only things that can be extended. It’s possible to extend any selector involving only a single element, such as .special.cool, a:hover, or a.user[href=”http://”]

속성을 한곳에만 정의 하고 @extend를 사용하여 같이 사용 할수 있습니다.

example.scss
1
2
3
4
5
6
.hoverlink {
  @extend a:hover;
}
a:hover {
  text-decoration: underline;
}
example.css
1
2
3
a:hover, .hoverlink {
  text-decoration: underline;
}

@extend a:hover을 사용 하면 선택자에 a.user:hover에서 a:hover를 제외한 문자만을 적용 합니다.

example.scss
1
2
3
4
5
6
.hoverlink {
  @extend a:hover;
}
.comment a.user:hover {
  font-weight: bold;
}
example.css
1
2
3
.comment a.user:hover, .comment .user.hoverlink {
  font-weight: bold;
}

Multiple Extends

.seriousError.error,.attention 두가지 속성 모두에 포함 됩니다.

example.scss
1
2
3
4
5
6
7
8
9
10
11
12
13
.error {
  border: 1px #f00;
  background-color: #fdd;
}
.attention {
  font-size: 3em;
  background-color: #ff0;
}
.seriousError {
  @extend .error;
  @extend .attention;
  border-width: 3px;
}
example.css
1
2
3
4
5
6
7
8
9
10
11
.error, .seriousError {
  border: 1px #f00;
  background-color: #fdd;
}
.attention, .seriousError {
  font-size: 3em;
  background-color: #ff0;
}
.seriousError {
  border-width: 3px;
}

Chanining Extends(확장 연결)

criticalError에서 @extend .seriousError함으로써 .seriousError에서 확장한 @extend error 까지 연결되서 확장 할수 있습니다.

example.scss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.error {
  border: 1px #f00;
  background-color: #fdd;
}
.seriousError {
  @extend .error;
  border-width: 3px;
}
.criticalError {
  @extend .seriousError;
  position: fixed;
  top: 10%;
  bottom: 10%;
  left: 10%;
  right: 10%;
}
example.css
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.error, .seriousError, .criticalEroor {
  border: 1px #f00;
  background-color: #fdd;
}
.seriousError, .criticalError {
  border-width: 3px;
}
.criticalError {
  position: fixed;
  top: 10%;
  bottom: 10%;
  left: 10%;
  right: 10%;
}

Selector Sequences

&상속은 a#fake-links .link 모두 상속을 받습니다.

example.scss
1
2
3
4
5
6
7
8
9
10
#fake-links .link {
  @extend a;
}

a {
  color: blue;
  &:hover {
    text-decoration: underline;
  }
}
example.css
1
2
3
4
5
6
a, #fake-links .link {
  color: blue;
}
  a:hover, #fakelinks .link:hover {
    text-decoration: underline;
  }

Merging Selector Sequences

두개의 다른 시퀀스를 @extend 할때는 첫번재 시퀀스, 첫번재 + 두번째 시퀀스, 두번째 시퀀스 + 첫번째 시퀀스를 한다. 마지막 셀렉터 .fakelink는 두번재 + 첫번재 시퀀스 뒤에 오게 됩니다.(왜?)

example.scss
1
2
3
4
5
6
#admin .tabbar a {
  font-weight: bold;
}
#demo .overview .fakelink {
  @extend a;
}
example.css
1
2
3
4
5
#admin .tabbar a,
#admin .tabbar #demo .overview .fakelink,
#demo .overview #admin .tabbar .fakelink {
  font-weight: bold;
}

두개의 시퀀스에 같은 셀렉터가 있을때.

example.scss
1
2
3
4
5
6
#admin .tabbar a {
  font-weight: bold;
}
#admin .overview .fakelink {
  @extend a;
}
example.css
1
2
3
4
5
#admin tabbar a,
#admin .tabbar .overview fakelink,
#admin .overview .tabbar .fakelink {
  font-weight: bold;
}

@extend-Only Selectors

selector 이름만 확장 할수 있습니다.

example.scss
1
2
3
4
5
6
7
8
#context a%extreme {
  color: blue;
  font-weight: bold;
  font-size: 2em;
}
.notice {
  @extend %extreme;
}
example.css
1
2
3
4
5
#context a.notice {
  color: blue;
  font-weight: bold;
  font-size: 2ex;
}

The !optional Flag

에러 발생시키는건데 왜 쓰는지 잘 모르겠습니다.

Normally when you extend a selector, it’s an error if that @extend doesn’t work. For example, if you write a.important {@extend .notice}, it’s an error if there are no selectors that contain .notice. It’s also an error if the only selector containing .notice is h1.notice, since h1 conflicts with a and so no new selector would be generated.

Sometimes, though, you want to allow an @extend not to produce any new selectors. To do so, just add the !optional flag after the selector.
example.scss
1
2
3
a.important {
  @extend .notice !optional;
}

@extend in Directives

There are some restrictions on the use of @extend within directives such as @media. Sass is unable to make CSS rules outside of the @media block apply to selectors inside it without creating a huge amount of stylesheet bloat by copying styles all over the place. This means that if you use @extend within @media (or other CSS directives), you may only extend selectors that appear within the same directive block
example.scss
1
2
3
4
5
6
7
8
9
10
@media print {
  .error {
    border: 1px #f00;
    background-color: #fdd;
  }
  .seriousError {
    @extend .error;
    border-width: 3px;
  }
}

But this is an error:

example.css
1
2
3
4
5
6
7
8
9
10
11
.error {
  border: 1px #f00;
  backgorund-color: #fdd;
}
@media print {
  .seriousError {
    // INVALID EXTEND: .error is used outside of the "@media print" directive
    @extend .error;
    border-width: 3px;
  }
}

@debug

debug.scss
1
@debug 10em + 12em;
1
Line 1 DEBUG: 22em

@warn

.css 컴파일시 조건에 해당 하면 경고문 출력

warn.scss
1
2
3
4
5
6
7
8
9
10
11
@mixin adjust-location($x, $y) {
  @if unitless($x) {
    @warn "Assuming #{$x} to be in pixels";
      $x: 1px * $x;
  }
  @if unitless($y) {
    @warn "Assuming #{$y} to be in pixels";
      $y: 1px * $y;
  }
  position: relative; left: $x; top: $y;
}

Control Directives

@if

if.scss
1
2
3
4
5
p {
  @if 1 + 1 == 2 { border: 1px solid; }
  @if 5 < 3      { border: 2px dotted; }
  @if nul        { border: 3px double; }
}
if.css
1
2
3
4
p {
  border: 1px solid;
  border: 3px double;
}

@if @else

if-else.scss
1
2
3
4
5
6
7
8
9
10
11
12
$type: monster;
p {
  @if $type == ocean {
    color: blue;
  } @else if $type == matador {
    color: red;
  } @else if $type == monster {
    color: green;
  } @else {
    color: black;
  }
}
if-else.css
1
2
3
p {
  color: green;
}

@for

from은 시작값 through는 최종 값입니다. $i값은 시작값 - 최종값 까지 1씩 더해 집니다.

for.scss
1
2
3
@for $i from 1 through 3 {
  .item-#{$i} { width: 2em * $i; }
}
for.css
1
2
3
4
5
6
7
8
9
.item-1 {
  width: 2em;
}
.item-2 {
  width: 4em;
}
.item-3 {
  width: 6em;
}

@each

puma, sea-slug, egret, salamander값들을 순서대로 #{$animal}값에 보간 합니다.

each.scss
1
2
3
4
5
@each $animal in puma, sea-slug, egret, salamander {
  .#{$animal}-icon {
    background-image: url('/images/#{$animal}.png');
  }
}
each.css
1
2
3
4
5
6
7
8
9
10
11
12
.puma-icon {
  background-image: url('/images/puma.png');
}
.sea-slug {
  background-image: url('/images/sea-slug.png');
}
.egret {
  background-image: url('/images/egret.png');
}
.salamander {
  background-image: url('/images/salamander.png');
}

@while

조건에 충족할때가지 반복 합니다.

while.scss
1
2
3
4
5
$i: 6;
@while $i > 0 {
  .item-#{$i} { width: 2em * $i; }
  $i: $i - 2;
}
while.css
1
2
3
4
5
6
7
8
9
.item-6 {
  width: 12em;
}
.item-4 {
  width: 8em;
}
.item-2 {
  width: 4em;
}

Mixin Directives

Defining a Mixin: @mixin

@mixin을 정의 합니다. @mixin 이름을 large-text로 정희 하고 large-text로 호출 할수 있습니다.

mixin.scss
1
2
3
4
5
6
7
8
@mixin large-text {
  font: {
    family: Arial;
    size: 20px;
    weight: bold;
  }
  color: #ff0000;
}

Mixins 부모 속성 포함

mixin-parent.scss
1
2
3
4
5
6
7
8
9
10
11
@mixin clearfix {
  display: inline-block;
  &:after {
    content: ".";
    display: block;
    height: 0;
    clear: both;
    visibility: hidden;
  }
  * html & { height: 1px }
}

Mixin 호출: @include

선언된 Mixin은 @include로 불러 올수 있습니다.

include.scss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@mixin large-text {
  font: {
    family: Arial;
    size: 20px;
    weight: bold;
  }
  color: #ff0000;
}

.page-title {
  @include large-text;
  padding: 4px;
  margin-top: 10px;
}
include.css
1
2
3
4
5
6
7
8
.page-title {
  font-family: Arial;
  font-size: 20px;
  font-weight: bold;
  color: #ff0000;
  padding: 4px;
  margin-top: 10px;
}
mixin-02.scss
1
2
3
4
5
6
7
8
@mixin silly-links {
  a {
    color: blue;
    background-color: red;
  }
}

@include silly-links;
mixin-02.css
1
2
3
4
a {
  color: blue;
  background-color: red;
}

Mixin 안에 Mixin @include

mixin 호출도 연계가 됩니다 compound를 호출 하면 heighlighted-background, header-text가 불립니다.

mixin-in-mixin.scss
1
2
3
4
5
6
7
8
9
10
11
@mixin compound {
  @include highlighted-background;
  @include header-text;
}

@mixin highlighted-background { background-color: #fc0; }
@mixin header-text { font-size: 20px; }

a {
  @inlucde compound;
}
mixin-in-mixin.css
1
2
3
a {
  background-color: #fc0;
  font-size: 20px }

Arguments

@mixin 호출시 인자 전달이 가능 합니다.

argument.scss
1
2
3
4
5
6
7
8
9
@mixin sexy-border($color, $witdh) {
  border: {
    color: $color;
    width: $width;
    style: dashed;
  }
}

p { @include secy-border(blue, 1in); }
argument.css
1
2
3
4
5
p {
  border-color: blue;
  border-width: 1in;
  border-style: dashed;
}

Mixin default value

기본값을 선언해줄수 있고 인자 전달이 없으면 기본 인자를 사용합니다.

mixin-default-value.scss
1
2
3
4
5
6
7
8
9
@mixin sexy-border($color, $width: 1in) {
  border: {
    color: $color;
    width: $width;
    style: dashed;
  }
}
p { @include sexy-border(blue); }
h1 { @include sexy-border(blue, 2in); }
mixin-default-value.css
1
2
3
4
5
6
7
8
9
10
p {
  border-color: blue;
  border-width: 1in;
  border-style: dashed;
}
h1 {
  border-color: blue;
  border-width: 2in;
  border-style: dashed;
}

Keyword Arguments

변수에 정의 하여 명시적으로 값을 전달 할수도 있습니다.

keyword.scss
1
2
p { @include sexy-border($color: blue); }
h1 { @include sexy-border($color: blue, $width: 2in); }

Varialbe Arguments

다수의 인자를 전달 받을때는 ...을 사용 해야 합니다.

variable-argument.scss
1
2
3
4
5
6
7
8
@mixin box-shadow($shadows) {
  -moz-box-shadow: $shadows;
  -webkit-box-shadow: $shadows;
  box-shadow: $shadows;
}
.shadows {
  @include box-shadow(0px 4px 5px #666, 2px 6px 10px #999);
}
variable-argument.css
1
2
3
4
5
.shadowed {
  -moz-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
  -webkit-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
  box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
}

Variable arguments calling a mixin

@mixin 호출시 인자 목록을 전달 할수있습니다.

call-mixin.scss
1
2
3
4
5
6
7
8
9
10
@mixin colors($text, $background, $border) {
  color: $text;
  background-color: $background;
  border-color: $border;
}

$values: #ff0000, #00ff00, #0000ff;
.primary {
  @include colors($values);
}
call-mixin.css
1
2
3
4
5
.primary {
  color: #ff0000;
  background-color: #00ff00;
  border-color: #0000ff;
}

wrap mixin and add styles change argument

@mixin에 전달 되는 인자를 또다르 @mixin에 전달 할수 있습니다. 다음의 코드는 컴파일은 되지 않습니다. 컴파일을 하려면 @mixin stylist-mixin을 선언해 주어야 합니다.

warp-mixin.scss
1
2
3
4
5
6
7
@mixin wrapped-stylish-mixin($args) {
    font-weight: bold;
    @include stylish-mixin($args);
}
.stylish {
  @include wrapped-stylish-mixin(#00ff00, $width: 100px);
}

Passing Content Blocks to a Mixin

@content html에 집어 널수도 있습니다.

mixin-content.scss
1
2
3
4
5
6
7
8
9
10
@mixin apply-to-ie6-only {
  * html {
    @content;
  }
}
@include apply-to-ie6-only {
  #logo {
    background-image: url(/logo.gif);
  }
}
mixin-content.scss
1
2
3
* html #logo {
  background-image: url(/logo.gif);
}

Variable Scope and Content Blocks

변수는 {}안에서 지역적으로 사용 됩니다.

scope.scss
1
2
3
4
5
6
7
8
9
$color: white;
  @mixin colors($color: blue) {
  background-color: $color;
  @content;
  border-color: $color;
}
.colors {
  @include colors { color: $color; }
}
scope.css
1
2
3
4
5
.colors {
  background-color: blue;
  color: white;
  border-color: blue;
}
scope-02.scss
1
2
3
4
5
6
7
#sidebar {
  $sidebar-width: 300px;
  width: $sidebar-width;
  @include smartphone {
    width: $sidebar-width / 3;
  }
}

Function Directives

function.scss
1
2
3
4
5
6
7
8
$grid-width: 40px;
$gutter-width: 10px;

@function grid-width($n) {
  @return $n * $grid-width + ($n - 1) * $gutter-width;
}

#sidebar { width: grid-width(5); }
function.css
1
2
#sidebar {
  width: 240px; }

Phonegap-Android

| Comments

사용 환경

  • 모델명 : MacBook Pro
  • 모델 식별자: MacBookPro8,1
  • 메모리: 4 GB
  • Eclipse: v4.2.1

요구 환경

  • Eclipse 3.4+

Eclipse Classic 설치

Eclipse 다운로드

이클립스 공식 사이트 Eclipse Classic에서 다운 받습니다.

"Eclipse down"

압축 해제및 실행

다운 받은 파일은 .tar.gz 압축 파일 이므로 압축 해제후 Eclipse 아이콘을 클릭 합니다.

Eclipse 실행

다음과 같은 페이지가 나오며 ok를 클릭 합니다.

"Eclipse 설치"

Android SDK 설치

Android 다운로드

안드로이드 개발 공식 사이트인 SDK에서 다운 받습니다.

"SDK Down"

Android SDK 환경 설정

파일 열기

1
$ vi ~/.bash_profile

.bash_profile 개인 SDK파일의 경로를 추가해 줍니다.

bash_profile
1
export PATH=${PATH}:/Development/android-sdk-macosx/platform-tools:/Development/android-sdk-macosx/tools

설정 확인

1
2
3
$ source ~/.bash_profile
$ echo $PATH
…./Users/han/Development/android-sdk-macosx/sdk/platform-tools:/Users/han/Development/android-sdk-macosx/tools….

Xcode Command Line Tools 설치

Xcode 실행후 > Xcode Preferences 선택 합니다.

"Command line 설치"

Downloads->Components-> Command Line Tools -> Install 클릭으로 설치 합니다.

"Command Line Tolls 설치"

설치가 끝나면 Terminal.app (iTerm)에서 커맨드 라인으로 작업을 할수가 있습니다. 자세한 사항은 Command-Line에서 iOS 부분을 참고 하시면 됩니다.

Apache Cordova 다운로드

다운로드된 파일은 .zip 파일이므로 압축을 풀어서 사용하시면 됩니다.

  • Cordova는 Cordova-Down에서 다운 받을수 있습니다.
  • 다운 받은 폴더를 ~/CordovaLib-2.x.x 쓰기 편한 위치로 이동 시킵니다.

새로운 프로젝트 시작하기

bin 폴더 열기

새로운 프로젝트를 생성하기 위해서는 ./create 파일을 실행 해야 합니다. create 파일은 lib/android/bin 폴더에 존재 합니다.

lib/ios/bin 폴더로 직접 이동 해서 사용할수 있습니다. 또는 ~/CordovalLib-2.2/lib/android/bin 폴더를 Terminal.app에 드래그 하면 bin 폴더로 바로 이동 할수 있습니다.

create 실행하기

사용 방법

lang: bash
1
$ ./create <project_folder_path> <package_name> <project_name>

create 사용

1
2
3
4
5
6
7
8
$ ./create <project_folder_path> pheonegap.start start
$ cd ~/project_folder_path
$ ls
AndroidManifest.xml   cordova   project.properties
ant.properties          gen     res
assets                    libs      src
bin                   local.properties
build.xml               proguard-project.txt

Eclipse 실행하기

SDK 지정 하기

eclipse를 처음 실행 하게 되면 다음과 같이 SDK 폴더를 지정합니다.

"SDK 지정"

SDK 경로 수정은 Command + , 사용해서 열수 있습니다.

Android SDK 매니저 설치

Android SDK 매니저 버튼을 클릭하거나 Window -> Android SDK Mannager를 클릭 합니다.

"Android SDK Mannager"

SDK 패키지 선택

모든 버전 보다는 현재 최신 버전과 Android 2.0대 까지만 있어도 충분 합니다.

"패키지 선택"

SDK 패키지 설치

체크된 패키지를 Install합니다.

"패키지 설치"

Android ADK Plugin 설치

안드로이드 개발 공식문서 사이트인 ADK Plugin에서 다운 받고 설치 가이드를 확인 할수 있습니다.

ADK 설치

Help -> insall new software를 클릭 합니다.

"install ADK"

화면 오른쪽 위에 ‘add’ 클릭

"클릭 Add"

Repository 추가

Location에서 문제가 발생하면 https -> http 사용하도록 합니다.

Name: ADT Plugin
Location: https://dl-ssl.google.com/android/eclipse/

"Add Repository 설정"

Available Software

Developer Tools과 필요한 프로그램을 클릭 한뒤 Next를 클릭합니다.

"Software 선택"

Install Details

인스톨 되는 정보를 확인후 Next를 클릭 합니다.

"Show Details"

Review Lienses

라이센스 확인후 Finish를 클릭 합니다.

"Finish click"

Security Warning

경고 화면이 나오게 되면 Ok를 클릭 하도록 합니다.

"Security Warning"

Software Update

설치가 끝나면 Yes를 클릭하여 새로 eclipse를 시작 하도록 합니다.

"Software Update"

ADV(Android Virtual Device Manager)

ADV 버튼을 클릭하거나 Window -> Anroid Virtual Devie Manger를 클릭 합니다.

"ADV"

ADV New

오른쪽 상단에 ‘New’ 버튼을 클릭 합니다.

"ADV New"

ADV Create

ADV 이름과 Device를 선택후 ok를 누릅니다.

"ADV Create"

Eclipse 실행

  1. Command line tools를 사용 하여 새로운 프로젝트를 만듭니다.
  2. 다운 받은 eclipse폴더에서 eclipse를 실행 합니다.
  3. eclipse에서 ‘File->New->Project’를 클릭 합니다.
  4. New Project 창에서 ‘Android Project from Existing Code’선택후 ‘Next’를 클릭 합니다.
  5. 우측 상단의 ‘Browse..’ 클릭후 생성된 Cordova 프로젝트폴더를 엽니다.
  6. Root Directory 정의후 ‘Run’실행 후 ADV를 선택 해주면 Android화면이생성
  7. Phonegap Android는 컴파일 시간이 오래 걸리므로 기다려 주어야 합니다.

Android Cordova 화면

완료된 Android 화면

"안드로이드 Cordova"

Phonegap-iOS

| Comments

사용 환경

  • 모델명 : MacBook Pro
  • 모델 식별자: MacBookPro8,1
  • 메모리: 4 GB
  • Xcode: v4.5.2
  • 기타:
    • homebrew
    • iTerm
    • Xcode Command Line Tools
    • OS X Mountain Lion
    • iPhone

요구 환경

  • Xcode 4.5+
  • Xcode Command Line Tools
  • Intel-based computer with Mac OS X Lion or greater (10.7+)
  • Necessary for installing on device:
    • Apple iOS device (iPhone, iPad, iPod Touch) iOS developer certificate

Xcode 설치

Xcode는 Mac App Store에서 다운 받아 설치 할수 있습니다.

Xcode Command Line Tools 설치

기존의 OS에서 생성 하던 방식이 Cordova.2.2.0 버전에서 부터는 Command Line Tools로 변경 되었습니다.

Xcode 실행후 > Xcode Preferences 선택 합니다.

"Xcode preferences 변경"

Downloads->Components-> Command LIne Tools -> Install 클릭으로 설치 합니다.

"Command Line Tools 설치"

설치가 끝나면 Terminal.app (iTerm)에서 커맨드 라인으로 작업을 할수가 있습니다. 자세한 사항은 공식 문서인 Command-Line에서 iOS 부분을 참고 하시면 됩니다.

Apache Cordova 다운로드

다운로드된 파일은 .zip 파일이므로 압축 해제후 사용 할수 있으며 Cordova는 Cordova-Down에서 다운 받을수 있습니다.

새로운 프로젝트 시작하기

bin 폴더 열기

새로운 프로젝트를 생성하기 위해서는 ./create 파일을 실행 해야 합니다. create 파일은 lib/iOS/bin 폴더에 존재 합니다.

~/you-cordova-path/lib/ios/bin 폴더로 직접 이동 해서 사용할수도 있고 ~/you-cordova-path/lib/ios/bin 폴더를 Terminal.app에 드래그하면 bin 폴더를 연후 사용할수도 있습니다.

create 실행하기

1
2
3
4
5
6
7
$ ./create <project_folder_path> <package_name> <project_name>

$ mkdir project_folder_path/new_folder_name
$ ./create <project_folder_path> pheonegap.start start
$ cd ~/project_folder_path
$ ls
CordovaLib    cordova     start       start.xcodepro www

Simulator 실행하기

project_name.xcodeproj 실행

project_name.xcodeproj 파일을 클릭 하면 Xcode가 실행 됩니다. 실행후 컴파일 시간을 거친후 아래와 같이 Run 우측에 project_name > iPhone v.xx Simulator 선택 한후 Run(단축키 Command + R)을 실행 시켜 줍니다.

"Simulrator 실행"

Run이 진행 되면 아래와 같은 iOS Simulator를 확인 할수 있습니다.

"Simulrator 실행 화면"

Less Tutorial

| Comments

Tutorial

Variables(변수)

변수 선언은 @ 연산자를 사용 합니다. 변수에 값을 정의 함으로써 광범위 하게 사용 할수 있습니다.

1
2
3
4
5
6
7
8
9
10
// example.less

@color: #4D926F

#header {
  color: @color;
}
h2 {
  color: @color;
}

.css로 변환 하면 @color의 값으로 치환됩니다.

1
2
3
4
5
6
7
8
// compile.css

#header {
  color: #4D926F;
}
h2 {
  color: #4D926F;
}

Mixins(믹스 인)

믹스인은 클래스 처럼 사용 가능 하며 클래스에서 설정한 모든 속성을 포함 시킵니다. 또한, 함수와 같이 인수를 설정 할수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// example.less

.rounded-corners (@radius: 5px) {
  -webkit-border-radius: @radius;
  -moz-border-radius: @radius;
  -ms-border-radius: @radius;
  -o-border-radius: @radius;
  border-radius: @radius;
}

#header {
  .rounded-corners;
}
#footer {
  .rounded-corners(10px);
}

.rounded-coners를 선언 하였고 기본 인수는 @radius5px입니다. #header는 기본 인수를 사용 하였고 #footer는 사용자 인수를 사용해 10px이 되었습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// compile.css

.rounded-corners (@radius: 5px) {
  -webkit-border-radius: @radius;
  -moz-border-radius: @radius;
  -ms-border-radius: @radius;
  -o-border-radius: @radius;
  border-radius: @radius;
}

#header {
  -webkt-boder-radius: 5px;
  -moz-border-radius: 5px;
  -ms-border-radius: 5px;
  -o-border-radius: 5px;
  border-radius: 5px;
}
#footer {
  -webkit-border-radius: 10px;
  -moz-border-radius: 10px;
  -ms-border-radius: 10px;
  -o-border-radius: 10px;
  border-radius: 10px;
}

Nested Rules(중첩 규칙)

선택기를 중첩하여 상속 가능하므로 긴 이름의 선택기를 중복으로 사용하지 않고도 명확하고 짧게 사용할수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// example.less

#header {
  h1{
    font-size: 26px;
    font-weight: bold;
  }
  p {
    font-size: 12px;
    a {
      text-decoration: none;
      &:hover { border-width: 1px }
    }
  }
}

.less 에서 한번 쓰인 #heder 선택기가 중복으로 적용됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
// compile.css

#header h1 {
  font-size: 26px;
  font-weight: bold;
}
#header p {
  font-size: 12px;
}
#header p a {
  text-decoration: none;
}
#header p a:hover { border-width: 1px }

Functions & Operations(함수와 연산)

연산은 색이나 숫자에 대해 덧셈, 뺄셈, 나눗셈, 곱셈을 할수 있습니다. 속성 사이에 복잡한 연산은 CSS의 호환성을 위해 괄호 내에서만 실행 됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// example.less

@the-border: 1px;
@base-color: #111;
@red: #842210;

#header {
  color: @base-color * 3;
  border-left: @the-border;
  border-right: @the-border * 2;
}
#footer {
  color: @base-color + #003300;
  border-color: desaturate( @red, 10%);
}
lang: css
1
2
3
4
5
6
7
8
9
10
11
// compile.css

#header {
  color: #333;
  border-left: 1px;
  border-right: 2px;
}    
#footer {
  color: #114411;
  border-color: #7d2717
}

The Language

Variables(변수)

LESS에서 변수는 실제로 상수로 기억되며 변수는 오직 한번만 정의 됩니다.

@nice-blue 변수를 선언하고 + 연산을 합니다.

1
2
3
4
5
6
// example-01.less

@nice-blue: #5B83AD;
@light-blue: (@nice-blue + #111);

#header { color: @light-blue; }
1
2
3
// example-01.css

#header { color: #6c94be; }

변수에 다른 변수를 정의 가능합니다.

1
2
3
4
5
6
// example-02.less
// @var에 문자열 'fnord'는 @fnord로 치환 됩니다.

@fnord: "I am fnord";
@var: 'fnord';
content: @@var;
1
2
3
// example-02.css

content: "I am fnord"

Mixins

Mixin은 이름을 사용해 선언 할수 있고 클래스 처럼 동작 합니다.

1
2
3
4
5
6
// example-03.less

.bordered {
  border-top: dotted 1px black;
  border-bottom: solid 2px black;
}

클래스 이름을 사용해 속성을 포함 시킬수있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// example-03.less

.bordered {
  border-top: dotted 1px black;
  border-bottom: solid 2px black;
}

#menu a {
  color: #111;
  .bordered;
}
.post a {
  color: red;
  .bordered;
}

선언된 .bordered.css에서 보이지 않으며 치환 된채로 컴파일 됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
// example-03.css

#menu a {
  color: #111;
  border-top: dotted 1px black;
  border-bottom: solid 2px black;
}
.post a {
  color: red;
  border-top: dotted 1px black;
  border-bottom: solid 2px black;
}

Mixins 인수 사용

클래스 처럼 믹스인 할수 있으며, 매개변수를 전달할수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// example-04.less

.border-radius (@radius) {
  border-radius: @radius;
  -moz-border-radius: @radius;
  -webkit-border-radius: @radius;
}

#header {
  .border-radius(4px);
}
.button {
  .border-radius(6px);
}

.button6px, #header에 4px 값을 전달 받아 선언합니다.

1
2
3
4
5
6
7
8
9
10
11
12
// example-04.css

#header {
  border-radius: 4px;
  -moz-border-radius: 4px;
  -webkit-border-radius: 4px;
}
.button {
  border-radius: 6px;
  -moz-border-radius: 6px;
  -webkit-border-radius: 6px;
}

매개 변수가 유효한 mixin은 기본값 5px을 가질수 있습니다

1
2
3
4
5
6
7
8
9
10
// example-05.less

.border-radius (@radius: 5px) {
  border-radius: @radius;
  -moz-border-radius: @radius;
  -webkit-border-radius: @radius;
}
#header {
  .border-radius;
}

기본 인수로 치환된 .css

1
2
3
4
5
6
7
// example-05.css

#header {
  border-radius: 5px;
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
}

정의된 선언 블록을 다른 규칙 세트에 이용하고 싶을때 정의된 규칙 세트 자체는 .css에 출력할 필요가 없을때 유용합니다.

1
2
3
4
5
6
7
8
9
// example-06.less

.wrap () {
    text-wrap: wrap;
    white-space: pre-wrap;
    white-space: -moz-pre-wrap;
    word-wrap: break-word;
}
pre { .wrap }
lang: css
1
2
3
4
5
6
7
8
// example-06.css

pre {
  text-wrap: wrap;
  white-space: pre-wrap;
  white-space: -moz-pre-wrap;
  word-wrap: break-word;
}

The @arguments varialbe

@arguments를 사용해서 개별적으로 파라미터를 사용 하지 않아도 되며, @x: 2px, @y:5px와 같이 선언된 순서와 전달된 순서로 매치 됩니다.

1
2
3
4
5
6
7
8
9
// example-07.less

.box-shadow (@x: 0, @y: 0, @blur: 1px, @color: #000) {
  box-shadow: @arguments;
  -moz-box-shadow: @arguments;
  -webkit-box-shadow: @arguments;
}

.box-shadow(2px, 5px);

0, 0값에서 전달된 2px, 5px값이 적용 됩니다.

1
2
3
4
5
// example-07.css

.box-shadow: 2px 5px 1px #000;
-moz-box-shadow: 2px 5px 1px #000;
-webkit-box-shadow: 2px 5px 1px #000;

패턴 매칭과 Guard 표현

기본 문법

mixin을 선언하고 조건문으로 인자를 비교해 같은 이름의 .mixin중에 참인 .mixin을 적용 합니다.

1
2
3
4
5
6
7
8
// basic-01.less

.mixin (@s, @color) {
    .
}
.class {
  .mixin(@switch, #888);
}

인수가 적용된 문법 표현

1
2
3
4
5
6
7
8
9
10
11
// basic-02.less

.mixin (dark, @color) {
  color: darken(@color, 10%);
}
.mixin (light, @color) {
  color: lighten(@color, 10%);
}
.mixin (@), @color) {
  display: block;
}

패턴 매칭과 Guard 표현 사용법

.mixin이 3개가 선언 되었고 각기 다른 조건문을 가지고 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// example-08.less

.mixin (dark, @color) {
  color: darken(@color, 10%);
}
.mixin (light, @color) {
  color: lighten(@color, 10%);
}
.mixin (@_, @color) {
  display: block;
}

@switch: light;
.class {
  .mixin(@switch, #888);
}

호출시 조건문의 light값을 충족하며 모든 값을 의미 하는 @_포함 하여 적용 됩니다.

1
2
3
4
5
6
// example-08.css

.class {
  color: #a2a2a2;
  display: black;
}

인수의 개수검사

1
2
3
4
5
6
.mixin (@a) {
  color: @a;
}
.mixin (@a, @b) {
  color: fade(@a, @b);
}

Guards

가드는 값이나 변수의 개수가 아니라 식에 일치 시킵니다. if/else 대신 when을 사용 합니다. @a값을 비교하여 적용 하며 인자가 하나이므로 color는 전체에 적용 됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
// example-09.less

.mixin (@a) when (lightness(@a) >= 50%) {
  background-color: black;
}
.mixin (@a) when (lightness(@a) < 50%) {
  background-color: white;
}
.mixin (@a) {
  color: @a;
}
.class1 { .mixin(#ddd) }
.class2 { .mixin(#555) }

조건에 따른 적용과 전체 적용된 color입니다.

1
2
3
4
5
6
7
8
9
10
// example-09.css

.class1 {
  color: #ddd;
  background-color: black;
}
.class2 {
  color: #555;
  background-color: white;
}

가드 안에서 비교식(>, >=, =, =<, <)

두개의 식은 같은 표현 입니다.

1
2
3
4
// basic.less

.truth (@a) when (@a) {  }
.truth (@a) when (@a = true) {  }

아래의 식은 위에 basic.less값에 매치 되지 않습니다. 값이 ‘true’만 매치 됩니다.

1
2
3
4
5
// example-10.less

.class {
  .truth(40);
}

조건문

  • = : 두 값이 같으면 참입니다.
  • not : 두 값이 같지 않으면 참입니다.
  • and : 모든 조건이 참이어야 합니다.
  • , : 모든 조건 값중에 하나만 참이면 참입니다.

JavaScript ‘or’와 Less ‘,’

JavaScript에서의 or와 같은 표현 조건중 하나만 참이어도 조건은 참입니다. 작성이 주의할점은 조건의 범위를 벗어난 값을 호출시 컴파일 자체가 되지 않습니다.

1
2
3
// example-11.less

.mixin (@a) when (@a > 10), (@a < -10) {  }

JavaScript ‘and’와 Less ‘and’

추가 조건문 and는 숫자인지 비교하고 0보다 높은 값이어야 합니다.

1
.mixin (@a) when (isnumber(@a)) and (@a > 0) {  }

부정 조건문 not

0보다 크지 않을때 동작

1
.mixin (@b) when not (@b > 0) {  }

인자비교및 대소 비교

1
2
3
4
5
6
7
8
9
// example-12.less

@media: mobile;

.mixin (@a) when (@media = mobile) {  }
.mixin (@a) when (@media = desktop) {  }

.max (@a, @b) when (@a > @b) { width: @a }
.max (@a, @b) when (@a < @b) { width: @b }

매개변수 number, color등 확인

1
2
.mixin (@a, @b: 0) when (isnumber(@b)) {  }
.mixin (@a, @b: black) when (iscolor(@b)) {  }

확인 가능한 is*형

  • iscolor
  • isnumber
  • isstring
  • iskeyword
  • isurl
  • ispixel
  • ispercentage
  • isem

Nested 법칙

& 콤비네이터를 사용한 상속을 통해서 간결하게 만들수 있습니다. 아래는 .css파일 입니다. 이를 .less로 바꾸어 보겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
// example-13.css

#header { color: black; }
#header .navigation {
  font-size: 12px;
}
#header .logo {
  width: 300px;
}
#header .logo:hover {
  text-decoration: none;
}

.css에서 반복 되던 #header를 한번만 선언 할수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
// example-13-01.less

#header {
  color: black;

  .navigation {
    font-size: 12px;
  }
  .logo {
    width: 300px;
    &:hover { text-decoration: none; }
  }
}

위와 결과는 같지만 더 간결한 문법을 보입니다.

1
2
3
4
5
6
7
8
// example-13-02.less

#header { color: black;
  .navigation { font-size: 12px }
  .logo       { width: 300px;
    &:hover   { text-decoration: none }
  }
}

example-14.less

& 콤비네이터 사용

1
2
3
4
5
6
7
8
// example-14.less

.bordered {
  &.float { flat: left; }
  .top {
    margin: 5px;
  }
}
1
2
3
4
5
6
7
8
// example-14.css

.bordered.float {
  flat: left;
}
.bordered.top {
  margin: 5px;
}

향상된 & 사용법

& 또다른 사용 법입니다. 모든 셀렉터의 조합을 만들어 줄수 있습니다.

1
2
3
4
5
6
7
8
9
10
// example-15.less

.child, .sibling {
  .parent & {
    color: black;
  }
  & + & {
    color: red;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
// example-15.css

.parent.child, .parent.sibling {
  color: black;
}

.child + .child,
.child + .sibling,
.sibling + .child,
.sibling + .sibling {
  color: red;
}

연산

숫자, 색, 변수를 연산 할수 있습니다.

1
2
3
4
5
6
7
8
9
// example-16.less

@base: 5%;
@filler: (@base * 2);
@other: (@bae + @filler);

color: (#888 / 4);
background-color: (@base-color + #111);
height: (100% / 2 + @filler);
1
2
3
// example-16-01.less

@var: (1px + 5); // @var: 6px
1
2
3
// example-16-02.less

width: ((@var + 5) * 2);

Color functions

밝기 조절

lighten(@color, 10%);
darken(@color, 10%);

채도 조절

saturate(@color, 10%);
desaturate(@color, 10%);

투명도

fadein(@color, 10%);
fadeout(@color, 10%);
fade(@color, 50%);

색장 조절

spin(@color, 10);
spin(@color, -10);

mix 사용법

@color1, 과 @color2 혼합된 값을 반환 합니다. @weight는 기본값 50%을 의미 합니다.

1
mix(@color1, @color2, @weight);

color luma 비교

@color1 > 50% luma 일경우 @darkcolor 를 아니면 @lightcolor를 반환 합니다.

1
contrast(@color1, @darkcolor, @lightcolor;);

color 사용법

1
2
3
4
5
6
7
8
// exampl1-17.less

@base: #f04615;

.class {
  color: saturate(@base, 5%);
  background-color: spin(lighten(@base, 25%), 8);
}

color 정보 추출

1
2
3
4
5
6
7
8
hue(@color) // `@color` 색상 반환
saturation(@color) // `@color` 채도값 반환
lightness(@color) // `@color` 밝기값 반환
red(@color) // `@color` 'red' 반환
green(@color) // `@color` `green`값 반환
blue(@color) // `@color` `blue`값 반환
alpha(@color) // `@color` `alpha`값 반환
luma(@color) // `@color` `luma`갑 반환

새로운 색 구하기

@new@old의 색을 유지하면서 자신의 채도 및 밝기를 정의

1
@new: hsl(hue(@old), 45%, 90%);

Math functions

1.67 전달시 2를 반환 합니다

round(1.67);

2.4 전달시 3을 반환 합니다.

ceil(2.4);

2.6 전달시 ‘2’를 반환 합니다.

floor(2.6);

퍼센티지 구하기

0.5전달시 50%를 반환 합니다.

percentage(0.5)

Namespaces

Namespace를 가지고 Mixin 에서 선택 할수 있습니다. 다음은 #bundle 에서 .button을 Mixin 하는 방법 입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// example-18.less

#bundle {
  .button () {
    display: block;
    border: 1px solid black;
    background-color: grey;
    &:hover { background-color: white }
  }
  .tab {  }
  .citaion {  }
}

#header a {
  color: orange;
  #bundle > .button;
}

.tab, .citaion은 적용 되지 않습니다.

1
2
3
4
5
6
7
8
9
10
11
// example-18.css

#header a {
  color: orange;
  display: black;
  border: 1px solid black;
  background-color: grey;
}
#header a:hover {
  background-color: #ffffff;
}

Scope

{ }안에서 변수 재선언시 지역적으로 사용 됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
// example-19.less

@var: red;

#page {
  @var: white;
  #header {
    color: @var;
  }
}
#footer {
  color: @var;
}

#page #hedaer{}안에서 선언된 @var의값으로 치환되고 #footer은 전역 적인 @var의 값으로 치환 됩니다.

1
2
3
4
5
6
#page #header {
  color: white;
}
#footer {
  color: red;
}

Less 주석 사용법

여러줄 주석 입니다. .css 변환시 에도 남아 있게 됩니다.

1
2
3
4
// example-20.less

/* Hello, I'm a CSS-style comment */
.class { color: black }

한줄 주석입니다 .css변환시 보이지 않습니다.

1
2
3
4
// example-21.less

// Hi, I'm a silent comment, I won't show up in your CSS
.class { color: white }

Importing

만들어진 .less 파일과 .css 파일을 호출 할수있습니다.

1
2
3
4
5
6
// example-22.less

@import "lib.less";
@import "lib";

@import "lib.css";

String interpolation

문자열을 "" 안에서 불러 올수 있습니다.

1
2
3
4
// example-23.less

@base-url: "http://assets.fnord.com";
background-image: url("@{base-url}/images/bg.png");

Selector Interpolation

셀렉터 이름도 불러 올수 있습니다.

1
2
3
4
5
6
// example-25.less

@name: blocked;
.@{name} {
  color: black;
}

@{name}@name의 값으로 치환 됩니다.

1
2
3
4
5
// example-25.css

.blocked {
  color: black;
}

Escaping

1
2
3
4
5
// example-24.less

.class {
  filter: ~"ms:alwaysHasItsOwnSyntax.For.Stuff()";
}
1
2
3
4
5
// example-24.css

.class {
  filter: ms:alwaysHasItsOwnSyntax.For.Stuff();
}

JavaScript evaluation

1
2
3
// example-26.less

@var: `"hello".toUpperCase() + '!'`;
1
2
3
// example-26.css

@var: "HELLO!";
1
2
3
4
// example-27.less

@str: "hello";
@var: ~`"@{str}".toUpperCase() + '!'`;
1
2
3
// example-27.css

@var: HELLO!;

JavaScript환경에 액세스 할수 있습니다.

1
@height:`document.body.clientHeight`;

Coffee Script 시작하기

| Comments

사용 환경

  • 모델명 : MacBook Pro
  • 모델 식별자: MacBookPro8,1
  • 프로세서 이름: Intel Core i5
  • 프로세서 속도: 2.3 GHz
  • 메모리: 4 GB
  • 기타: homebrew, iTerm

CoffeeScript 설치

CoffeeScript - CoffeeScript is a little language that compiles into JavaScript

CoffeeScript 공식 사이트

CoffeeScript 공식 사이트 주소는 CoffeeScript 사이트 입니다.

npm - coffee-script 설치를 위한 패키지 매니저

coffee-script를 다운 받기 위해서는 npm이 필요 하고 별도로 설치 해야 하며 npm 설치를 위한 파일은 아래의 링크에서 다운로드 받습니다.

npm 다운로드

node-v.8.x.x.pkg 설치

개인 OS에 맞는 파일을 선택해 다운 받고 설치 합니다. 다음은 Mac 에서의 .pkg 실행시 첫화면과 마지막 화면 입니다.

"node.pkg 설치 시작" "node.pkg 설치 끝"

coffee-script 설치

npm을 사용해 coffee-script를 설치해 줍니다.

hancho@hanjoui-MacBook-Pro:~$ sudo npm install -g coffee-script
Password:
npm http GET https://registry.npmjs.org/coffee-script
npm http 304 https://registry.npmjs.org/coffee-script
/usr/local/bin/coffee -> /usr/local/lib/node_modules/coffee-script/bin/ coffee
/usr/local/bin/cake -> /usr/local/lib/node_modules/coffee-script/bin/cake
coffee-script@1.4.0 /usr/local/lib/node_modules/coffee-script

CoffeeScript 사용방법

CoffeeScript 시작하기

테스트를 위한 폴더를 생성후 `style.less` 파일을 만듭니다.

   $ mkdir Coffee-Start
   $ cd Coffee-Start
   $ touch style.coffee

style.coffee 작성

coffee가 동작 확인을 위해 테스트 파일를 작성합니다.

style.coffee
1
2
3
4
fill = (container, liquid = "coffee") ->
  "Filling the #{container} with #{liquid}..."

alert fill("cup")

.coffee -> .js 변환하기

.coffee 파일 작성후 .js 파일로 변환합니다. 파일명은 style.coffee의 style.js로 변환됩니다.

    $ coffee --compile style.coffee
    $ ls
    style.coffee style.js

.coffee -> .js 지켜보기

--watch 옵션으로 style.coffee 파일 내용이 갱신(저장)시 .js파일로 변환 됩니다. 종료는 Ctrl + C 키로 할수있습니다.

    $ coffee --watch --compile style.coffee
    11:55:26 - compiled style.coffee

coffeescript - .coffee 확인 하기

.html 파일 내에서 .js 파일로 변환 없이 .coffee를 검사 할수있습니다.

coffee.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html>
  <head>
  <script src="http://jashkenas.github.com/coffee-script/extras/coffee-script.js" type="text/javascript" charset="utf-8"></script>
  <script type="text/coffeescript">
    fill = (container, liquid = "coffee") ->
      "Filling the #{container} with #{liquid}..."

    alert fill("cup")
  </script>
  </head>

  <body>
  </body>
</html>

coffeescript - .js 확인하기

.html 파일 내에서 변환된 .js 내용을 검사 할수있습니다.

coffee.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<html>
  <head>
  <script src="http://jashkenas.github.com/coffee-script/extras/coffee-script.js" type="text/javascript" charset="utf-8"></script>
  <script>
    var fill;

    fill = function(container, liquid) {
      if (liquid == null) {
        liquid = "coffee";
      }

      return "Filling the " + container + " with " + liquid + "...";
    };

    alert(fill("cup"));
  </script>
  </head>

  <body>
  </body>
</html>

Sass 시작하기

| Comments

Sass - Syntactically Awesome Stylesheets

사용 환경

  • 모델명 : MacBook Pro
  • 모델 식별자: MacBookPro8,1
  • 프로세서 이름: Intel Core i5
  • 프로세서 속도: 2.3 GHz
  • 메모리: 4 GB
  • 기타: homebrew, iTerm

Sass 설치

Sass 공식 사이트

Sass의 공식 사이트 주소는 Sass 사이트입니다.

gem - Sass 설치를 위한 패키지 매니저

gem을 사용하려면 Ruby가 설치되어 있어야 합니다. gem 설치가이드

RVM 패키지 설치

ruby를 설치 하기전 ruby를 관리해주는 RVM 을 설치 합니다. 처음 실행 시키면 q를 누르라고 나옵니다. q 입력후 설치 시간이 좀 걸리게 되며 아래와 같은 내용이 나올때까지 기다려야 합니다.

$ curl -L https://get.rvm.io | bash -s stable --ruby

ruby-1.9.3-p327 - #extracting ruby-1.9.3-p327 to /Users/hancho/.rvm/src/ruby-1.9.3-p327
ruby-1.9.3-p327 - #extracted to /Users/hancho/.rvm/src/ruby-1.9.3-p327
ruby-1.9.3-p327 - #configuring
ruby-1.9.3-p327 - #compiling
ruby-1.9.3-p327 - #installing 
Removing old Rubygems files...
Installing rubygems-1.8.24 for ruby-1.9.3-p327 ...
Installation of rubygems completed successfully.
Saving wrappers to '/Users/hancho/.rvm/bin'.
ruby-1.9.3-p327 - #adjusting #shebangs for (gem irb erb ri rdoc testrb rake).
ruby-1.9.3-p327 - #importing default gemsets (/Users/hancho/.rvm/gemsets/)
Install of ruby-1.9.3-p327 - #complete 
Creating alias default for ruby-1.9.3-p327.
Recording alias default for ruby-1.9.3-p327.
Creating default links/files
Saving wrappers to '/Users/hancho/.rvm/bin'.

* To start using RVM you need to run `source /Users/hancho/.rvm/scripts/rvm`
in all your open shell windows, in rare cases you need to reopen all shell windows.

Ruby 설치

RVM이 설치가 정상적으로 완료되면 rvm 을 사용해 루비를 설치해 줍니다.

$ rvm install 1.9.3

A RVM version 1.16.20 (stable) is installed yet 1.14.5 (stable) is loaded.
Please do one of the following:
* 'rvm reload'
* open a new shell
* 'echo rvm_auto_reload_flag=1 >> ~/.rvmrc' # for auto reload with msg.
* 'echo rvm_auto_reload_flag=2 >> ~/.rvmrc' # for silent auto reload.

ruby 버전별 사용

ruby 버전을 최신으로 설정해 줍니다.

$ rvm use 1.9.3

Using /Users/hancho/.rvm/gems/ruby-1.9.3-p327

ruby 최신 버전 적용

현재 보다 최신 버전이 있으면 최신 버전으로 적용 시켜 주게 됩니다. 현재 사용하고 있는 버전이 최신이 아니었다면 위의 $ rvm use 1.x.x 사용 하는게 좋습니다.

$ rvm rubygems latest

Removing old Rubygems files...
Installing rubygems-1.8.24 for ruby-1.9.3-p327 ...
Installation of rubygems completed successfully.

Sass 설치

RVM과 Ruby가 정상적으로 설치되면 sass를 설치 할수 있습니다.

$ gem install sass

Sass 사용방법

Sass 따라 해보기

테스트 폴더를 생성후 `style.scss` 파일을 만듭니다.

   $ mkdir Sass-Start
   $ cd Sass-Start
   $ touch style.scss

style.scss 파일 작성

sass 동작 확인을 위해 테스트 파일를 작성합니다.

style.scss
1
2
3
4
5
6
7
8
9
10
11
12
.fakeshadow {
  border: {
    style: solid;
    left: {
      width: 4px;
      color: #888;
    }
    right: {
      width: 2px;
      color: #ccc;
    }
  }

.scss -> .css 변환하기

작성된 .scss 파일을 .css 파일로 변환합니다. 다음은 .scss 파일이 변경 되었을시 재입력 없이 변경 되는 명령어 입니다. .scss 파일이 변경되는 시점에(저장시) .css 변환을 자동으로 해주므로 수정 사항이 많을시 사용해 주면 좋습니다.

$ sass --watch style.scss:style.css

LESS 시작하기

| Comments

LESS - The Dynamic Stylesheet Language

사용 환경

  • 모델명 : MacBook Pro
  • 모델 식별자: MacBookPro8,1
  • 프로세서 이름: Intel Core i5
  • 프로세서 속도: 2.3 GHz
  • 메모리: 4 GB
  • 기타: homebrew, iTerm

LESS 설치

LESS 공식 사이트

LESS의 공식 사이트 주소는 LESS 사이트입니다.

npm - LESS 설치를 위한 패키지 매니저

LESS를 다운 받기 위해서는 npm이 필요 하고 별도로 설치를 해주어야 하며 npm 설치를 위한 필요한 파일은 아래의 링크에서 다운로드 받을수 있습니다.

npm 다운로드

node-v.8.x.x.pkg 설치

개인 OS에 맞는 파일을 선택하여 다운 받았다면 이를 설치 합니다. 다음은 Mac 에서의 .pkg 실행시 첫화면과 마지막 화면 입니다.

"node.pkg 설치 시작" "node.pkg 설치 끝"

LESS 설치

정상적으로 패키지 설치가 완료 되면 npm을 사용해 LESS를 설치 합니다.

$ npm install -g less

LESS 사용방법

LESS 시작하기

테스트 폴더를 생성하고 style.less 파일을 만듭니다.

   $ mkdir Less-Start
   $ cd Less-Start
   $ touch style.less

style.less 작성

less의 동작 확인을 위한 테스트 파일를 작성합니다.

style.less
1
2
3
4
5
6
7
8
  @color: #4D926F;

  #header {
    color: @color;
  }
  h2 {
    color: @color;
  }

.less -> .css 미리보기

`.less` 작성후 변환하기전 `.css` 미리 보기를 할수 있습니다.

   $ lessc styles.less

   #header {
     color: #6cc4be;
   }

.less -> .css 변환하기

작성이 완료되면 `.less` 파일을 `.css` 파일로 변환하여 줍니다.

   $ lessc styles.less > styles.css
   $ ls
   styles.less styles css