compile your style

Download Compile your Style

If you can't read please download the document

Upload: ragnar-kurm

Post on 16-May-2015

1.121 views

Category:

Technology


2 download

DESCRIPTION

Using different kind of tools to build big styles for websites. Problem with big CSS is that it gets heavy, hard to manage, convoluted. But fortunately there are ways to keep structured and manageable. In this presentation we introduce combination of Makefile, SASS, ImageMagick, and other tools.

TRANSCRIPT

  • 1. Ragnar Kurm | DrupalCamp Baltics Estonia, Tallinn | 2013 Compile your Style https://github.com/ragnarkurm/compile-your-style http://www.slideshare.net/ragnarkurm/compile-your-style-25500334

2. Ragnar Kurm 25 years of programming 5 years of Drupal 30 Drupal sites 1 big & busy community site 3. Audients Those who build a big theme(s) Those who are specialized on theming 4. What we will learn Description Tools and methods Style Preprocessor SASS Style speed Selector matching and specificity Structuring the Style Split and join Style files Style building automation Makefile Automatic Image processing ImageMagick Multiple layouts Makefile, SASS, ImageMagick 5. When your Style gets too fat Repeating and dependent values Style too slow Files too big http://www.waltsense.com/home/2010/4/23/too-fat-to-fight.html 6. When your theme gets too heavy Loss of overview Lack of structure Hard to manage http://benhartnett.com.au/artworkandplay/2009/hard-walking/ 7. Repeating and dependent values 8. The problem and the solution The problem A specific value used for many times. Example: main style color. A specific value used to derive other valus. Example: calculation of spacing values The solution Preprocessor Example: Sass 9. Example SASS $blue: #3bbfce $space: 16px .one, .two padding: $space / 2 p color: darken($blue, 9%) CSS .one, .two { padding: 8px; } .one p, .two p { color: #2b9eab; } 10. Usage shell> sass global.sass global.css This compiles a .sass file into a .css file. 11. More about Preprocessor Numbers, colors, strings Variables Calculations Conditions Functions and arguments Style reuse File inclusion 12. Speed of the Style 13. The problem and the solution The problem Big style ruleset makes page rendering slow in a browser. Symptom: browser hangs for a moment before displaying a page The solution Learn how selector matching works: speed selectivity 14. Speed: Selector matching examples #main-navigation { } /* ID (Fastest) */ body.home #page-wrap { } /* ID */ .main-navigation { } /* Class */ ul li a.current { } /* Class * ul { } /* Tag */ ul li a { } /* Tag */ * { } /* Universal (Slowest) */ #content [title='home'] /* Universal */ #main-nav > li { } /* Slower than it might seem */ ul#main-navigation { } /* Don't */ html body ul li a { } /* Worst */ http://css-tricks.com/efficiently-rendering-css/ 15. Speed: Selector matching rules Matching happens from right to left Failing rules are quicker than matching rules Google: css selector speed 16. Specificity: Calculation A selector's specificity is calculated as follows: count the number of ID selectors in the selector (= a) count the number of class selectors, attributes selectors, and pseudo-classes in the selector (= b) count the number of type selectors and pseudo-elements in the selector (= c) ignore the universal selector Concatenating the three numbers a-b-c (in a number system with a large base) gives the specificity. http://www.w3.org/TR/css3-selectors/#specificity 17. Specificity: Examples * /* a=0 b=0 c=0 -> specificity = 0 */ LI /* a=0 b=0 c=1 -> specificity = 1 */ UL LI /* a=0 b=0 c=2 -> specificity = 2 */ UL OL+LI /* a=0 b=0 c=3 -> specificity = 3 */ H1 + *[REL=up] /* a=0 b=1 c=1 -> specificity = 11 */ UL OL LI.red /* a=0 b=1 c=3 -> specificity = 13 */ LI.red.level /* a=0 b=2 c=1 -> specificity = 21 */ #x34y /* a=1 b=0 c=0 -> specificity = 100 */ #s12:not(FOO) /* a=1 b=0 c=1 -> specificity = 101 */ http://www.w3.org/TR/css3-selectors/#specificity 18. Example: classes for Views grid

This is simplification Only most relevant bits are shown Default classes are stripped to minimum Only custom classes are used for theming 19. Too big Style files 20. Symptoms * Convoluted code* Convoluted code * Hard to keep track* Hard to keep track * Hard to manage* Hard to manage * Loss of overview* Loss of overview * Hard to read :)* Hard to read :) 21. Solution Structuring: Split and join Use automation: Makefile 22. Structuring the Style Definitions file Elements Structural Fields Views Nodes Pages 23. Definitions file Path(s) for example: /sites/www.example.com/files/ Image style dimensions matches Drupal Configuration > Image Styles Image dimensions generated from actual images Dimensions Like margins, certain element widths, different layout sizes, etc Colors custom color definitions CSS snippets reusable CSS code like rounded() Included by all other .sass files. Concatenated from pieces. 24. CSS Pieces Elements / General tags Pager Structural / Zones Zone-header Zone-footer Regions Regions-header-first Regions-footer-first Blocks Block-main-menu Fields / Forms Type-display Type-form Type-boolean-display Type-boolean-form Field-like-display Field-like-form Views / Views My-grid My-table Product-list Member-list Nodes / Node Book Article Pages / Front Contact Node-add 25. Join the Pieces The easy way Include all pieces together (example: a.sass) @import "includes/defs.sass" @import "elements/admin-menu.sass" @import "elements/ads.sass" @import "elements/feedback.sass" @import "elements/help.sass" @import "elements/image.sass" @import "elements/system.messages.sass" Compile the file sass a.sass a.css 26. Automation: The Makefile The hard way Tesla factory in Fremont, California 27. What is a Makefile Utility make and rules file Makefile are used to do automation Makefile specifies rules how to make target files and what files does it depend on If dependency file is newer, the target will be remade 28. Automatics schematics global.css piece3.css piece2.css piece1.css piece3.sass piece2.sass piece1.sass 29. Example 1/2: variables # Assign individual files to variables GLOBAL = global.css DEFS = include/defs.sass # The variable ELEMENTS is assigned list of files # with directory and without suffixes ELEMENTS = $(addprefix elements/,tagsadmin-menu feedback) # same for other piece-sets STRUCTURAL = $(addprefix structural/, ) FIELDS = $(addprefix fields/, ) VIEWS = $(addprefix views/, ) NODES = $(addprefix nodes/, ) PAGES = $(addprefix pages/, ) # all pieces PIECES = $(ELEMENTS) $(STRUCTURAL) $(FIELDS) $(VIEWS) $(NODES) $(PAGES) # append .css PIECES_CSS = $(addsuffix .css, $(PIECES)) 30. Example 2/2: rules # rule to generate final .css # target depends on all .css pieces # if any .css is missing it will be generated # if any .css is newer than target, then the target will be regenerated $(GLOBAL): $(PIECES_CSS) cat $^ > $@ # rule to compile arbitrary .sass to .css # if any required .css is missing it will be generated from corresponding .sass file # if any required .css is older than corresponding .sass it will be regenerated %.css: %.sass sass $< $@ # any piece .css file depends on Makefile and definitions file # if something is changed in Makefile or in definitions # then all required .css files will be recompiled $(PIECES_CSS): Makefile $(DEFS) # kill all generated stuff clean: rm -f $(PIECES_CSS) $(GLOBAL) find . -name '.sass-cache' -type d -print0 | xargs -0 rm -rf 31. Automatic variables $@ The file name of the target of the rule. $@ is the name of whichever target caused the rule's recipe to be run. $< The name of the first prerequisite. $^ The names of all the prerequisites, with spaces between them. $* The stem with which an implicit rule matches. In a static pattern rule, the stem is part of the file name that matched the % in the target pattern. http://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html 32. Execution Clean up all stuff from previous compilation (rarely) shell> make clean rm -f elements/tags.css elements/admin-menu.css elements/feedback.css structural/a.css global.css find . -name '.sass-cache' -type d -print0 | xargs -0 rm -rf Compile your theme (constantly) shell> make sass elements/tags.sass elements/tags.css sass elements/admin-menu.sass elements/admin-menu.css sass elements/feedback.sass elements/feedback.css sass structural/a.sass structural/a.css cat elements/tags.css elements/admin-menu.css elements/feedback.css structural/a.css > global.css 33. Explanation The example above describes a way to compile one big .css file from multitude of .sass files. Executed by 'make'. It knows exactly the dependency tree and (re)generates all necessary files when needed. It has instruction how to clean up all generated files. Executed by 'make clean'. 34. Multiple layouts Drupal theme Seven 35. What we need SASS handling for environment variables Tool to extract image dimensions for SASS Image conversion Layout styling to individual pieces Layout settings to definitions file Layout handling to Makefile 36. Environment variables for SASS Create file lib/env.rb as module/plugin/lib for SASS module Sass::Script::Functions def env(var) assert_type var, :String Sass::Script::String.new(ENV[var.to_s()]) end end Using the module/plugin/lib sass --require lib/env.rb 37. Automated image operations ImageMagick is free software suite to create, edit, compose, or convert bitmap images. convert convert between image formats as well as resize an image, blur, crop, despeckle, dither, draw on, flip, join, re-sample, and much more. identify describe the format and characteristics of one or more image files. 38. ImageMagick one-liners http://www.imagemagick.org/Usage/ 39. Image dimensions for SASS Shell script that extracts image dimensions shell> cat ./wh #!/bin/sh img="$1" label=`echo "$img" | tr 'a-z-' 'A-Z_' | sed 's/.[A-Z]*$//'` identify -format "$WIDTH_$label: %wpx" "$img" identify -format "$HEIGHT_$label: %hpx" "$img" Usage and output of the script shell> ./wh logo-big.png $WIDTH_LOGO_BIG: 100px $HEIGHT_LOGO_BIG: 50px 40. Image derivation schematics logo.png logo-wide.png logo-normal.png logo-narrow.png logo-wide.sass logo-normal.sass logo-narrow.sass 41. Image conversion LOGO = logo.png PNG =logo-widelogo-normallogo-narrow DERIVATIVES = $(addsuffix .png, $(PNG)) DIMENSIONS = $(addsuffix .sass, $(PNG)) all: $(DERIVATIVES) $(DIMENSIONS) logo-wide.png: $(LOGO) convert $< -geometry 200x $@ logo-normal.png: $(LOGO) convert $< -geometry 150x $@ logo-narrow.png: $(LOGO) convert $< -geometry 100x $@ $(DERIVATIVES): Makefile %.sass: %.png ./wh $< > $@ clean: rm -f $(DERIVATIVES) $(DIMENSIONS) In image directory there is separate Makefile. It deals with automatic image conversion for different layouts. Executed by 'make'. In this particular example logo.png is resized for 3 different layouts. In addition dimensions will be extracted for these images for SASS inclusion. Should the designer change the logo, possibly even changing its dimensions, 'make' will handle that. 42. Layout styling to individual pieces @import "includes/defs.sass" @if $LAYOUT == "global" @if $LAYOUT == "alpha-default" #logo display: block background-position: center background-repeat: no-repeat @if $LAYOUT == "alpha-default-narrow" #logo width: $WIDTH_LOGO_NARROW height: $HEIGHT_LOGO_NARROW background-image: url($IMG + "logo-narrow.png") @if $LAYOUT == "alpha-default-normal" #logo width: $WIDTH_LOGO_NORMAL height: $HEIGHT_LOGO_NORMAL background-image: url($IMG + "logo-normal.png") @if $LAYOUT == "alpha-default-wide" #logo width: $WIDTH_LOGO_WIDE height: $HEIGHT_LOGO_WIDE background-image: url($IMG + "logo-wide.png") This SASS compiles into 4 CSS files according to if statement. It styles #logo element for different layouts. It uses the logo image's dimensions which is set up automatically. It uses $IMG to save you from carpal tunnel syndrome. 43. Layout settings to definitions file Common definitions file includes all image dimensions which are used in any layout SASS variable LAYOUT will be assigned according to environment variable LAYOUT: $LAYOUT: env(LAYOUT) Layout-specific definitions $SPACER: 0 @if $LAYOUT == "global" @if $LAYOUT == "alpha-default" @if $LAYOUT == "alpha-default-narrow" $SPACER: 10px @if $LAYOUT == "alpha-default-normal" $SPACER: 15px @if $LAYOUT == "alpha-default-wide" $SPACER: 20px This SASS code assigns layout- dependent value(s) to variable(s). 44. Layout schematics global.css alpha-default.css piece1.global.css piece2.global.css piece1.alpha-default.css piece2.alpha-default.css piece1.sass piece2.sass 45. Layout handling to Makefile TARGET = $(LAYOUT).css LAYOUTS =globalalpha-defaultalpha-default-narrowalpha-default-normalalpha-default-wide PIECES_CSS = $(addsuffix .$(LAYOUT).css, $(PIECES)) all: for layout in $(LAYOUTS); domake $$layout.css -e LAYOUT=$$layout|| exit 1 ;done $(TARGET): $(PIECES_CSS) cat $^ > $@ %.$(LAYOUT).css: %.sass LAYOUT=$(LAYOUT)sass --require lib/env.rb $< $@ $(PIECES_CSS): Makefile $(DEFS) clean: for layout in $(LAYOUTS); domake clean-$$layout -e LAYOUT=$$layout|| exit 1 ;done clean-$(LAYOUT): rm -f $(PIECES_CSS) rm -f $(TARGET) This Makefile is not complete It is extension to earlier one This Makefile works by using environment variable LAYOUT This makefile works by executing itself in different context (env LAYOUT value). The environment variable LAYOUT is available as Makefile variable $(LAYOUT) This Makefile produces one stylesheet for each layout named as layout.css Each layout.css is concatenation of css pieces named as name.layout.css which are compiled from name.sass 46. Difference between the easy way and the hard way Speed difference ca 10x If (easy_way.compile() == too_slow) then goto hard_way; Remember that during theming process compilation is very frequent procedure 47. What did we learn Description Tools and methods Style Preprocessor SASS Style speed Selector matching and specificity Structuring the Style Split and join Style files Style building automation Make / Makefile Automatic Image processing ImageMagick Multiple layouts Make / Makefile, SASS, ImageMagick 48. Further reading Scalable and Modular Architecture for CSS http://smacss.com/