Tableless

Busca Menu

Analisando o código Stylus de um projeto

Seja o primeiro a comentar por

O que é um pré-processador CSS?

Como o nome ja diz, é uma linguagem que precisa ser pré-processada por um parser para assim gerar o arquivo de extensão .css que será renderizado pelo browser. Atualmente há vários pré-processadores que você pode utilizar para facilitar a codificação e reaproveitamento de código, você pode estar utilizando SASS, LESS e Stylus que são os mais conhecidos no mercado. A diferença do Stylus para os outros pré-processadores que estão sendo utilizados no mercado é que ele já é baseado em NodeJS e não em ruby. Por conta disso não há necessidade de uma tecnologia intermediária em seu workflow para processá-lo.

Vamos começar!

Tendo em mente que você ja conhece um pouco sobre pré-processadores e algumas de suas vantagens (variáveis, mixins, operadores, funções) vamos criar um projeto utilizando algumas dessas funcionalidades.

  1. Faça o download do NodeJS e efetue a instalação;
  2. Considerando que tenha o node rodando em seu sistema, instale o Stylus de forma global e execute o seguinte comando em seu terminal npm install -g stylus;
  3. Vamos criar a estrutura de diretórios de nosso projeto:

Após ter seu diretório criado de acordo com a estrutura da imagem acima, você pode acessá-lo via terminal com o comando cd /seu-diretorio e na sequência executar o compilador stylus da seguinte maneira:

stylus -w a

Parâmetros

  • -w (Observar alterações nos arquivos .styl e re-compilar gerando os arquivos resultantes .css);
  • -o (Após este parâmetro deve ser passado o caminho que deve ser salvo o arquivo compilado);

Desmistificando a Estrutura

ASSETS

Costumo sempre utilizar esta estrutura como raíz para os diretórios front-end principalmente pela facilidade em migrar para servidores independentes e também para evitar confusão entre o pessoal de back-end.

ASSETS/css

Arquivos gerados após executar o pré-processador, gerando assim os arquivos com extensão .css prontos para utilização em seu código.

ASSETS/stylus

Neste diretório fica toda a nossa organização de diretórios e arquivos .styl (Extensão utilizada pelo Stylus).

ASSETS/stylus/base (Tipografia, reset, variáveis, cores)

O nome dos arquivos em si é bem descritivo, colors.styl para cores, variables.styl para variáveis reutilizáveis, typography.styl para definições de fonts e reset.styl (reset de elementos css).

ASSETS/stylus/components (Pequenos componentes)

Utilizado para pequenos componentes como botões, formulários, modals e o que surgir de necessidade conforme o desenvolvimento de seu projeto.

ASSETS/stylus/helpers (Utilitários para seus projetos)

Neste diretório geralmente são encontrados os seguintes arquivos: functions.styl, helpers.styl (classes utilitárias ex.: .pull-left, .show), mixins.styl (são blocos de códigos reutilizáveis semelhantes a funções).

ASSETS/stylus/layout (Definições do seu layout)

Você vai encontrar os arquivos com definições de estilo com a cara do seu layout, como header, footer e grid.

ASSETS/stylus/theme (Temas do projeto)

Definições de temas do projeto. Caso o projeto tenha mais de um tema, é uma boa prática para manter a organização e facilidade de manutenção no código.

ASSETS/stylus/main.styl

Este é o arquivo primário que será lido pelo seu compilador, deve possuir todas as importações necessárias para gerar o arquivo .css resultante. Obs: Todos os arquivos all.styl servem para facilitar a importação no arquivo principal.

Botando a mão na massa

Uma vez que você compreendeu a ideia dos diretórios criados e está com o compilador rodando corretamente, vamos ao código:

assets/stylus/base

all.styl (Import de todos os arquivos do diretório)

// Import all from base
<a title="Twitter profile for @import" href="http://twitter.com/import" target="_blank" rel="nofollow">@import</a> ‘reset.styl’
<a title="Twitter profile for @import" href="http://twitter.com/import" target="_blank" rel="nofollow">@import</a> ‘colors.styl’
<a title="Twitter profile for @import" href="http://twitter.com/import" target="_blank" rel="nofollow">@import</a> ‘typography.styl’
<a title="Twitter profile for @import" href="http://twitter.com/import" target="_blank" rel="nofollow">@import</a> ‘variables.styl’

colors.styl (Definições de cores do projeto)

orange = #FF6347
gray-darker = #AAAAAA
gray-lighter = #EEEEEE
lighter = #FFF
darker = #444444
blue = #0080FF
blue-lighter = #1EC0FF
yellow = #F9C00C
red = #E71D36
green = #3AC569

reset.styl (Foi utilizado o normalize.css)

normalize.css

typography.styl (Definições de fonts)

font-size-h1 = 40px
font-size-h2 = 34px
font-size-h3 = 28px
line-height-h1 = 55px
line-height-h2 = 46px
line-height-h3 = 38px
h1, h2, h3
 color darker
 font-weight bold
h1
 font-size font-size-h1
 line-height line-height-h1
 color darker
 margin-bottom 30px
h2
 font-size font-size-h2
 line-height line-height-h1
h3
 font-size font-size-h3
 line-height line-height-h3

variables.styl (Variáveis reutilizáveis do projeto)

// Font Weights
light = 300
regular = 400
bold = 700
// Base Font
base-font-family = ‘Open Sans’, sans-serif
base-font-weight = light
base-font-size = 20px
base-line-height = 27px
form-label-font-size = base-font-size
form-field-font-size = 18px
// Buttons
btn-font-weight = bold
btn-default-border = gray-darker
btn-default-color = darker
btn-primary-color = lighter
btn-success-color = lighter
btn-danger-color = lighter
btn-warning-color = lighter
btn-info-color = lighter

assets/stylus/components

all.styl

// Import all from components
@import ‘buttons.styl’
@import ‘forms.styl’

buttons.styl

.btn
 font-weight bold
 padding 15px 27px
 border 1px solid transparent
 display inline-block
 cursor pointer
 border-radius(5px)
&-info
 &-primary
 &-success
 &-danger
 color lighter
&-default
 color darker
 border-color gray-darker
 background-color lighter
&-primary
 background-color blue
 border-color blue
&:hover
 &:focus
 background-color darken(blue, 20%)
 border-color darken(blue, 20%)
&-info
 background-color blue-lighter
 border-color blue-lighter
&:hover
 &:focus
 background-color darken(blue-lighter, 20%)
 border-color darken(blue-lighter, 20%)
&-warning
 background-color yellow
 border-color yellow
&:hover
 &:focus
 background-color darken(yellow, 20%)
 border-color darken(yellow, 20%)
&-success
 background-color green
 border-color green
&:hover
 &:focus
 background-color darken(green, 20%)
 border-color darken(green, 20%)
&-danger
 background-color red
 border-color red
&:hover
 &:focus
 background-color darken(red, 20%)
 border-color darken(red, 20%)

forms.styl

.form
 &__group
 margin-bottom 20px
&__label
 color darker
 font-size form-label-font-size
 font-weight bold
 margin-bottom 10px
&__field
 display block
 width 100%
 padding 6px 18px
 height 60px
 border 1px solid gray-darker
 color darker
 font-size form-field-font-size
 border-radius(3px)
&:hover
 &:focus
 border-color orange

helpers.styl (Utilitários do projeto)

all.styl (Import de todos os arquivos do diretório)

// Import all from helpers
@import ‘functions.styl’
@import ‘helpers.styl’
@import ‘mixins.styl’

functions.styl

make-media-queries-breakpoints()
 for screen-width in screen-desktop-large screen-desktop screen-tablet screen-mobile
 @media only screen and (max-width: screen-width)
 if (screen-width == screen-desktop-large)
 .container
 width container-desktop
 else if (screen-width == screen-desktop)
 .container
 width container-tablet
 else if (screen-width == screen-tablet)
 .container
 .columns
 width container-mobile !important
make-row()
 margin 0 (-(grid-gutter-width / 2))
calc-container-padding()
 padding 0 (grid-gutter-width / 2)
make-columns()
 for i in grid-columns..0
 .col-{i}
 width percentage(i, grid-columns)
.col-offset-{i}
 margin-left percentage(i, grid-columns)
percentage(index, divider)
 if index == 0
 0
 else
 unit((index * 100) / divider, “%”)

helpers.styl (Classes utilitárias para uso no html)

.pull-left
 float left
.pull-right
 float right
.show
 display block
.hide
 display none
.text-center
 text-align center
.text-left
 text-align left
.text-right
 text-align right
.absolute
 position absolute
.relative
 position relative
.in-block
 display inline-block
.center-block
 margin 0 auto
 display block
.img-responsive
 max-width 100%
.clearfix
 &:before
 &:after
 content “ “
 display table
&:after
 clear both

mixins.styl

vendor(prop, args)
 -webkit-{prop} args
 -moz-{prop} args
 {prop} args
border-radius()
 vendor(‘border-radius’, arguments)
box-shadow()
 vendor(‘box-shadow’, arguments)
opacity(n)
 opacity n
 filter unquote(‘progid:DXImageTransform.Microsoft.Alpha(Opacity=’ + round(n * 100) + ‘)’)

assets/stylus/layout

header.styl

.header
 background-color orange
 padding 30px 0
.header__img
 max-width 150px

footer.styl

.footer
 padding 40px 0
 background-color darker
 color lighter
& a
 color lighter
 &:hover
 color orange
& p
 font-size 16px
 line-height 22px
 margin 0 0 10px 0
& .fa
 color #E84545
 margin 0 2px
& img
 max-width 150px
 &:hover
 opacity(0.6)

grid.styl (Sistema de grids utilizado no projeto)

// Media Queries Breakpoints
screen-desktop-large = 1200px
screen-desktop = 992px
screen-tablet = 768px
screen-mobile = 480px
// Grid System
grid-columns = 12
grid-gutter-width = 30px
// Container Sizes
container-desktop-large = 1170px
container-desktop = 940px
container-tablet = 720px
container-mobile = 100%
.container
 width container-desktop-large
 calc-container-padding()
 margin 0 auto
.row
.columns
 box-sizing border-box
.row
 make-row()
&:before
 &:after
 content “ “
 display table
&:after
 clear both
.columns
 @extend .relative
 @extend .pull-left
 padding 0 (grid-gutter-width / 2)
make-media-queries-breakpoints()
make-columns()

login.styl

.content
 padding-top 60px
 padding-bottom 60px
 min-height 470px
&__login
 padding 30px
 border-radius(3px)
 background-color gray-lighter
 box-shadow(0 0 5px rgba(0,0,0,0.09))
 max-width 530px
 background-color darker
& .form__label
 & h3
 color lighter
& h3
 margin-bottom 20px

assets/stylus/themes (Temas do projeto admin, padrão e quais forem necessários)

default.styl (Tema padrão)

*
 vendor(‘box-sizing’, border-box)
body
 font-family base-font-family
 font-weight base-font-weight
 font-size base-font-size
 line-height base-line-height
 background-color lighter
a
 text-decoration none

assets/stylus/main.styl (Arquivo principal)

Neste arquivo você deve efetuar todas as importações necessárias do seu projeto. Em nosso tutorial o arquivo ficou assim:

@charset “UTF-8”
@import ‘base/all.styl’
@import ‘helpers/all.styl’
@import ‘components/all.styl’
// Imports from layout
@import ‘layout/grid.styl’
@import ‘layout/header.styl’
@import ‘layout/footer.styl’
@import ‘layout/login.styl’
// Import themes
@import ‘themes/default.styl’

Por fim, crie um arquivo index.html na raíz de seu projeto com o seguinte código:

<!DOCTYPE html>
<html lang=”en”>
<head>
 <meta charset=”UTF-8">
 <title>Iniciando com Stylus</title>
<link href=”https://fonts.googleapis.com/css?family=Open+Sans:300,400,700" rel=”stylesheet”>
<link rel=”stylesheet” href=”https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<link rel=”stylesheet” href=”assets/css/main.css”>
</head>
<body>
 <header class=”header”>
 <div class=”container”>
 <img class=”header__img img-responsive center-block” src=”assets/images/stylus-logo.png” alt=”” />
 </div>
 </header>
<div class=”content container”>
 <h1 class=”text-center”>Iniciando com Stylus</h1>
<div class=”content__login center-block”>
 <h3 class=”text-center”>Acesse sua conta</h3>
<form action=”#”>
 <div class=”form__group”>
 <label for=”name” class=”form__label show”>Nome</label>
<input type=”text” name=”name” id=”name” class=”form__field”>
 </div>
 <div class=”form__group”>
 <label for=”email” class=”form__label show”>Email</label>
<input type=”text” name=”email” id=”email” class=”form__field”>
 </div>
 <div class=”submit text-right”>
 <button type=”submit” class=”btn btn-success”>
 Submit
 </button>
 </div>
 </form>
 </div>
 </div>
<footer class=”footer text-center”>
 <div class=”container”>
 <p>
 Feito com <i class=”fa fa-heart”></i> por <a href=”http://helderburato.com/”>Helder Burato Berto</a>
 </p>
<a class=”in-block” href=”http://uilab.com.br/">
 <img class=”img-responsive” src=”assets/images/uilab-logo.png” alt=””>
 </a>
 </div>
 </footer>
</body>
</html>

Compreendendo a linguagem Stylus

Você pode observar que foram utilizados algumas particularidades da linguagem, que não são comuns para quem está acostumado apenas com CSS, sendo elas: &: Usado para referenciar parcialmente um elemento citado anteriormente, por exemplo:

.foo
 color #000
 & a
 color #fff

Será compilado para:

.foo {
 color: #000;
}
.foo a {
 color: #fff;
}

Você percebe o quanto isso é poderoso e tem utilidade?

border-radius(): Mixin definido para ser reutilizado e com possibilidade de uso com parâmetros.

Exemplo de uso:

.foo
 border-radius(5px)

Será compilado para:

.foo {
 border-radius: 5px;
 -webkit-border-radius: 5px;
 -moz-border-radius: 5px;
}

Observe que foi gerado o código ja com os prefixos para outros browsers, facilitando na escrita.

IF e FOR: Vamos descrever o uso de IF e for com uma função que foi utilizado no tutorial chamada make-media-queries-breakpoints().

make-media-queries-breakpoints()
 for screen-width in screen-desktop-large screen-desktop screen-tablet screen-mobile
 @media only screen and (max-width: screen-width)
 if (screen-width == screen-desktop-large)
 .container
 width container-desktop
 else if (screen-width == screen-desktop)
 .container
 width container-tablet
 else if (screen-width == screen-tablet)
 .container
 .columns
 width container-mobile !important

Nós utilizamos o FOR para percorrer as variáveis declaradas posteriormente e IF para modificar a width de nosso container principal de acordo com a media queria utilizada.

O código acima após a compilação:

@media only screen and (max-width: 1200px) {
 .container {
 width: 1170px;
 }
}
@media only screen and (max-width: 992px) {
 .container {
 width: 720px;
 }
}
@media only screen and (max-width: 768px) {
 .container,
 .columns {
 width: 100%;
 }
}

Sintaxe

Você provavelmente deve ter percebido que com Stylus não temos a necessidade do uso de {} e; nas declarações CSS, isso em prática ajuda muito na produtividade.

Variáveis

Você pode declarar variáveis sem o uso de $ mas caso você já utilizou outros pré;-processadores, fica a seu crité;rio o uso dele ou não.

Bom espero que tenha conseguido compartilhar um pouco do que é; esta grande ferramenta e que lhe seja útil na hora de pensar em usar um pré;-processador.

Um grande abraço, obrigado!

Publicado no dia