Let's write pretty code. – But let's talk about making websites. – These are preprocessors.



Let's write pretty code. – But let's talk about making websites. – These are preprocessors.

0 0


minnebar2016

Slide Deck for Minnebar 2016

On Github AhoyLemon / minnebar2016

Let's write pretty code.

Hi, I'm Lemon.

I make websites.

A lot of websites.

Big ones like...

  • General Mills
  • United Health Group
  • Ramada Plaza
  • Lifetime Fitness
  • 3M
  • Minnesota Wild
  • US Bank
Little ones like...
  • The Wrongest Words
  • Recent Firings In San Francisco
  • damn.dog

The best game on the internet

Gizmodo

I tweet sometimes.

@AhoyLemon

If you tweeted at me during this, that would be fine. Some people find it rude, but I like the attention.

I also do a podcast.

It's called The F Plus. We read terrible things with enthusiasm.

I'm proud of it, but it probably isn't appropriate for your workplace.

Anyway, you can go to thefpl.us for that.

But let's talk about making websites.

When I make websites I use...

But really, all that technology amounts to...

But to me, that means...

And that's what we're gonna talk about today.

Well, Jade and Sass. We'll skip javascript for now.

These are preprocessors.

What is a preprocessor?

It's a way for you, as a developer to write quicker, prettier, more maintainable code, and let the computers do the crappy parts.

Okay, let's use this as an example...

Pretty code in...

.tech-logos { @include flex-container(); @extend %gutters;
  .logo { @include flex-item(20%,0); }
}

Ugly code out...

.reveal .tech-logos { display: -webkit-flex;
                      display: -ms-flexbox;
                      display: flex;
                      -webkit-flex-direction: row;
                      -ms-flex-direction: row;
                      flex-direction: row;
                      -webkit-flex-wrap: wrap;
                      -ms-flex-wrap: wrap;
                      flex-wrap: wrap;
                      padding-top: 1em;
                      padding-bottom: 1em; }
.reveal .tech-logos .logo { width: 20%; 
                            -webkit-flex-basis: 20%;
                            -ms-flex-preferred-size: 20%;
                            flex-basis: 20%;
                            -webkit-flex-grow: 0;
                            -ms-flex-positive: 0;
                            flex-grow: 0;
                            -webkit-flex-shrink: 1;
                            -ms-flex-negative: 1;
                            flex-shrink: 1;
                            -webkit-align-self: auto;
                            -ms-flex-item-align: auto;
                            align-self: auto; }

That was all

Sass stands for Syntactically Awesome StyleSheets

The only rule: Don't capitalize Sass.
Because Hampton Catlin will be disappointed in you.

Hampton also made

It looks like this...

#content
  .left.column
    %h2 Welcome to our site!
    %p= print_information
  .right.column
    %label
      %span Enter your name
      %input(type=text selected)

But I use...

It looks like this...

#content
  .left.column
    h2 Welcome to our site!
    p= information
  .right.column
    label
      span Enter your name
      input(type=text selected)

Haml

#content
  .left.column
    %h2 Welcome to our site!
    %p= print_information
  .right.column
    %label
      %span Enter your name
      %input(type=text selected)

Jade

#content
  .left.column
    h2 Welcome to our site!
    p= information
  .right.column
    label
      span Enter your name
      input(type=text selected)
7% fewer characters!*

*This statistic from the same place Carly Fiorina gets her facts from.

By the way...

Apparently Jade is called Pug now?

That seems unncessary.

But here's the logo...

Let's just keep calling it Jade.

To do all this stuff, you'll need a Task Runner.

A task runner can do a number of things, but the main use is that when you save a file, it'll process it into a different kind of file.

There's a number of them to choose from.

BUT, these are command line tools...

CAN A BROTHER GET A GUI!?

Because there's also...

Personally, I use Prepros.

Prepros supports

And it does image compression too.
Download & Install Add to project Tweak settings if you like.

Now you can write Sass & Jade.

But why should I write Sass?

nesting imports variables mixins extends BONUS: auto prefixing

LET'S TRY THEM ALL!!!

1. nesting

The most immediate change you can make.

.topnav { position:fixed; top:0; right:0; left:0; height:4rem;
  .inner { padding-left:10px; padding-right:10px; }
  a { color:white; text-decoration:none;
    &.big { font-size:1.3em; }
    &:hover { background:white; color:black; }
  }
}

Sass

.topnav { position:fixed; top:0; right:0; left:0; height:4rem;
  .inner { padding-left:10px; padding-right:10px; }
  a { color:white; text-decoration:none;
    &.big { font-size:1.3em; }
    &:hover { background:white; color:black; }
  }
}

CSS

.topnav { position:fixed; top:0; right:0; left:0; height:4rem; }
.topnav .inner { padding-left:10px; padding-right:10px; }
.topnav a { color:white; text-decoration:none; }
.topnav a.big { font-size:1.3em; }
.topnav a:hover { background:white; color:black;  }

Any CSS file is already valid Sass.

Just change your .css file to .scss, and you're ready to start nesting.

⚠️ A BRIEF WARNING ⚠️

While nesting is useful, it can (like anything programming related) get out of hand.

If you can help it, try to limit your nesting to 4 deep

.because {
  .this {
    .is {
      .not {
        .how {
          .you {
            .should {
              .write {
                .code { color:lime; }
              }
            }
          }  
        }
      }
    }
  }
}

People get opinionated about this, but you'll be fine.

2. imports

@import "globals/_variables";
@import "globals/_mixins";
@import "globals/_reset";

@import "sections/_header";
@import "sections/_main";
@import "sections/_footer";

@import "pages/_home";
@import "pages/_error";
@import "pages/_email";

With imports, you can break all your code into small, manageable pieces.

Move stuff around at will, or yank out entire imports and laugh at their demise. The world is yours!

This also prevents stuff like this...

The client wants you to change the footer CSS

Good luck!

Personally, I do dozens of imports in a project.

I keep them organized by what the block of code does, with broader ideas sharing a folder together.

That works for me, but you do you.

3. variables

// FONTS
$font-size:14px;
$light:300;
$bold:700;
$slab:'Roboto Slab', serif;

// COLORS
$white:#f0f1f2;
$black:#333;
$red:#b22028;

// MEASUREMENTS 
$topnav-height: 4rem;
$mobile-max:780px;
$desktop-min:781px;

Let's code...

body { font-family:$font; font-size:$font-size; background:$white; color:$black; }
h1 { font-weight:$bold; }
header { height:$topnav-height;
  .inner { height:($topnav-height / 2) }
}
@media screen and (max-width:$mobile-max) {
  header { display:none; }
}

Variables means not having 17 accidental variations of the color red.

Or z-index:9999999;

Or changing the code a hundred times because the logo needed more padding.

4. mixins

@mixin flex-container($align:stretch, $direction:row, $wrap:wrap) {
  display: flex;
  flex-direction: $direction;
  flex-wrap: $wrap;
  @if ($align != "stretch") {
    align-items: $align;
  }
}

@mixin flex-item($basis, $grow:1, $shrink:1, $align:auto) {
  @if $grow == 0 {
    width:$basis;
    flex-basis: $basis;
  } @else {
    flex-basis: $basis;
  }
  flex-grow: $grow;
  flex-shrink: $shrink;
  align-self: $align;
}

@mixin respond-to($media) {
  @if $media == desktop {
    @media only screen and (min-width: $desktop-min) { @content; }
  }
  @else if $media == mobile {
    @media only screen and (max-width: $mobile-max) { @content; }
  }
}

@mixin flex-split($desktop, $mobile) {
  @include respond-to(desktop) { @include flex-item($desktop); }
  @include respond-to(mobile) { @include flex-item($mobile); }
}

💖 Mixins are terrific! 💖

You can define basic ideas with default values, then alter those values for specific cases.

Which is like, kind of the point of CSS.

5. extends

%inner { width: 100%; max-width:$max-width; margin-left:auto; margin-right: auto; }
%clearfix {
  &:after { content: ""; display: table; clear: both; }
}
%quote {
  &:before { content: '\201C'; }
  &:after { content: '\201D'; }
}
header, main, footer { @extend %inner;
  .float-container { @extend %clearfix; }
}
blockquote {
  p { @extend %quote; }
}

Use extends whenever you notice you're typing the same series of commands.

If you see a design with a lot of the same padding, borders, shadows or hover effects used frequently, throw those in an extend.

This will make it much easier to change if when the designer changes her mind about how they should look.

mixins, extends, and variables work great with imports!

None of these will end up in your processed CSS until they're actually used, so you can horde them like a dragon.

REUSE THEM!

I have about a dozen Sass partials that I carry over into every new project, so I can keep writing the same code.

Also to prevent myself for looking up the hex code for Facebook Blue for the 100th time.

BONUS: Auto Prefixing

This is technically not a Sass thing, but you get it.

And you'll like it.

Let's talk animation!

We're gonna make a sunrise...

Sass

@keyframes sunrise {
  0% { bottom: 0; left: 340px; background: #f00; }
  33% { bottom: 340px; left: 340px; background: #ffd630; }
  66% { bottom: 340px; left: 40px; background: #ffd630; }
  100% { bottom: 0; left: 40px; background: #f00; }
}
.sun { animation: 10s ease infinite; }

CSS

@-webkit-keyframes sunrise { 
  0% { bottom: 0; left: 340px; background: #f00; }
  33% { bottom: 340px; left: 340px; background: #ffd630; }
  66% { bottom: 340px; left: 40px; background: #ffd630; }
  100% { bottom: 0; left: 40px; background: #f00; }
}

@keyframes sunrise { 
  0% { bottom: 0; left: 340px; background: #f00; }
  33% { bottom: 340px; left: 340px; background: #ffd630; }
  66% { bottom: 340px; left: 40px; background: #ffd630; }
  100% { bottom: 0; left: 40px; background: #f00; }
}  
.sun { -webkit-animation: 10s ease infinite; animation: 10s ease infinite; }

On every save, your preprocessor applies the prefixes.

Writing -ms-flex is for chumps.

Okay, so that's Sass.

So what's this about

So, why should I write Jade?

A lot of the same reasons....
HTML is dumb variables includes mixins each/while loops You're basically an expert at Sass now

1. HTML is dumb

That's not fair.

HTML was made by smart people, but it is basically immovable.

Any new stuff that's added to HTML has to exist alongside code that was approved in 1999.

Because of this, you end up typing weird things.

Everything in HTML has to be closed.

Except when it doesn't.
<input type="text" disabled="disabled" />
<textarea required="required"></textarea>
<h1>Headline</h1>
<hr />
<input type="submit" value="Submit" />
<button type="submit">Submit</button>

A representative sample of Facebook's code

<div>
  <div>
    <div>
      <div>
        <div>
          <div>
            <div>
              <div>
                <script src="SomeStupidTrackingScript.js"></script>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
Source: Carly Fiorina

Jade is indentation based.

.so
  .whenever
    .you want to
      .nest
        .just hit
          .tab
<div class="so">
  <div class="whenever">
    <div class="you">want to
      <div class="nest">
        <div class="just">hit
          <div class="tab"></div>
        </div>
      </div>
    </div>
  </div>
</div>

With Jade, you only write the parts you need to.

h3.jade-headline#JadeHeadline With 
  span.green Jade
  | , you 
  i  only  
  code write the parts 
  span.bigger you 
    b need
    |  to.
<h3 id="JadeHeadline" class="jade-headline">
  With
  <span class="green">Jade</span>, you 
  <i> only </i>
  <code>write the parts</code>
  <span class="bigger">you 
    <b>need</b> to.
  </span>
</h3>

2. variables

- var pageTitle = "Your Lucky Number"
- var lastUpdated = "04.20.2016"
- var luckyNumber = Math.floor((Math.random() * 100) + 1);
head
  title= pageTitle
  link(href="css/minnebar.css?updated=#{lastUpdated})
body
  h1 Your lucky number is
    span.number= luckyNumber

Just like Sass, you can define and redefine variables, and use them anywhere.

But unlike Sass, you can use any javascript function you like to create those variables.

Random numbers, conditional iterations, it's madness I tells ya, madness!

3. includes

doctype html
html(lang="en")
  head
    include partials/head.jade
  body
    include partials/topnav.jade
    
    main
      h1 Welcome to my home page!
    
    include partials/footer.jade
    include partials/javascripts.jade

Partials allow you to only write things once.

Global markup is bound to change sometimes. By keeping everything segmented, you can reuse all the parts you'd otherwise have to write more than once.

Who needs PHP!?

...well, probably you.

(but maybe not.)

Unless you need a client-facing CMS, Jade can do most of the stuff you'd otherwise use PHP for.

Build some HTML and host it on GitHub for free.

4. mixins

mixin button(text, url)
  if url
    a.active-button= text
  else
    .placeholder= text
    
+button("VISIT GOOGLE", 'http://google.com')
+button('This is not a button')

💖 Mixins are terrific! 💖

I know I said this earlier, but unfettered javascript accesss makes mixins even better.

Let's make a placeholder...

mixin placeholder(caption, height, width)
  - var tinaQuotes = ["Everyone touch each other's butts", "My heart!", "I put my bra on one boob at a time like everyone else.", "Dad, I need you to drop everything and shave my legs"]
  if !caption
    - caption = tinaQuotes[n]
  if !height
    - height = 600
  if !width
    - width = Math.floor((Math.random() * 600) + 500);
  figure
    img(src="https://unsplash.it/#{width}/#{height}")
    figcaption= caption
  n++
  
+placeholder("Hi boys, I'm Tina.",400,850)
+placeholder("If boys had uteruses they’d be called duderuses")
+placeholder()

Here's what that looks like...

Hi boys, I'm Tina.If boys had uteruses they’d be called duderuses.I put my bra on one boob at a time like everyone else.

5. each/while loops

- var testamonials = [ 
    {text: "This Sass & Jade presentation is the Crank: High Voltage of tech talks!", cite: "Jason Statham"  },
    {text: "Lemon just made me like a million times smarter", cite: "Neil DeGrasse Tyson" },
    {text: "I heard this whole presentation is a terrorist conspiracy", cite: "Carly Fiorina" },
    {text: "Butts.", cite: "Tina Belcher" }
    ]
each quote in testamonials
  blockquote
    p= quote.text
    cite= quote.cite

People are raving about this presentation!

This Sass & Jade presentation is the Crank: High Voltage of tech talks!

Jason Statham

Lemon just made me like a million times smarter

Neil DeGrasse Tyson

I heard this whole presentation is a terrorist conspiracy

Carly Fiorina

Butts.

Tina Belcher

6. and now....

you're good at this.

like, really good at this.

Holy crap.

Okay,new languages are hard.

And with both of these languages, I had times where I wished I was writing code the old way.

But when you get good at this stuff, you improve your workflow.

You write better, you write quicker, and you get the knowledge of knowing a new thing.

Thanks for listening.

This slidedeck was written in Jade, Sass, and Reveal.js

Available online at ahoylemon.github.io/minnebar2016

@AhoyLemon