Painting with Onions

http://meis.github.io/talks/Painting-with-Onions || @m_e_i_s

Ladies and gentlemen, welcome to the

DISCLAIMER

(Sorry for the lack of kitties and memes)

WHO HATES CSS?

Everyone?

IT IS NOT CSS's FAULT

(entirely)

CSS is for HTML

HTML is for DOCUMENTS

CSS is for HTML

HTML is was for DOCUMENTS

CSS problems

CSS problems

Multiple implementations

CSS problems

Cascade


body {
  color: red
}
button {
  font-family: Comic Sans;
}

Also, not all the properties work the same way (tables, em, etc)

CSS problems

GLOBALS


body {
  color: red
}
button {
  font-family: Comic Sans;
}

CSS problems

"I've changed my mind" extension method


button {
  font-family: Comic Sans;
}
...

button {
  font-family: Any other font, please;
}

CSS problems

Non-standard module system

Bower?

Last include wins

CSS problems

Paths of files


.icon {
  width: 32px;
  height: 32px;
  background: url(path/to/my/icon.png))
}

CSS problems

Backward compatibility

Don't break the internet

CSS problems

We don't see CSS as code

Current approaches

And why I don't like them

LESS, SASS & family

Preprocessors

  • Variables
  • Import/include files
  • CSS compatible
  • Mixins

LESS, SASS & family

Preprocessors

  • Cascade
  • Globals
  • No standard 'extend' method

CSS frameworks

(Bootstrap)

  • Minium effort
  • Allows theming
  • You can extend (with work)

CSS frameworks

  • You're tied (it's not your HTML anymore)
  • You can theme XOR extend
  • Frameworks don't mix well

CSS in JS

(Angular, React, Polymer, etc)

CSS in the template system

var style = { color: 'white' };

React.render(
Hi!
, mountNode);

CSS in JS

  • Extensible
  • Real programming language
  • Avoid globals
  • Can be distributed (npm)

CSS in JS

  • Coupling templates with style
  • Impossible to reuse outside the framework
  • Cascade is still present
  • Hard to cache
  • Corner cases: @media?

CONTROL SLIDE

Can Perl help?

I think so

My Approach

  • Using a real programming language
    • Perl

My Approach

  • Compile to CSS
    • Compatibility
    • Use your own markup
    • Cache

My Approach

  • Let the compiler be the CSS expert
    • Specificity
    • Performance
    • Dependencies

My Approach

Ideas using Moose

  • Components
  • Manifests
  • Compiler

Onions::Component

UI element

Onions::Component


package My::Button;
use Moose;
extends 'Onions::Component';

sub _build_attributes {{
  color  => 'green',
  border => '1px solid black',
}}

Onions::Component


package My::FancyButton;
use Moose;
extends 'My::Button';

sub _build_attributes {{
  color  => 'red',
  border => '1px solid black',
}}

Onions::Component


package My::PerlIcon;
extends 'Onions::Component';

sub _build_attributes {{
  background_image => $_[0]->files('image');
}}

sub _build_files {{
  image => 'file_in_this_package',
}}

Onions::Manifest

Export variables

Onions::Manifest


package Onions::Manifest::DesktopApp;
use Moose;
extends 'Onions::Manifest';

sub _build_variables {{
  font_family   => 'Comic Sans',
  font_size     => '12px',
  window_border => '1px solid black',
  button_color  => 'green',
}}

Onions::Manifest


package My::DesktopApp::Theme
extends 'Onions::Manifest:DesktopApp';

sub _build_variables {{
  font_family   => 'Comic Sans',
  font_size     => '18px',
  button_color  => 'red',
}}

Onions::Manifest


package My::Button;

with_manifest 'DA' => 'Onions::Manifest::DesktopApp';

sub _build_attributes {
  my $self = shift;
  {
    font_family => $self->variablre('DA', 'font_family'),
    font_size   => $self->variablre('DA', 'font_size'),
    color       => $self->variablre('DA', 'button_color'),
  }
}

Onions


my $o = Onions->new();

$o->let('button')
  ->be('Onions::Component::Button')
  ->with_theme('DA', 'My::DesktopApp::Theme');

$o->let('#icon-perl')->be('My::PerlIcon');

$o->files_root('/img');
$o->dump_files('path/to/img');
$o->dump_css('path/to/file.css');

Onions


button {
  font-family: Comic Sans;
  font-size: 12px;
  color: red;
}
#icon-perl {
  background: url('/img/MyPerlIconImage.png');
}

Key points

  • Components define ALL the styles
  • Compiler will use cascading (or not)
  • Themeable + Extensible frameworks
  • Multiple Manifests at the same time
  • Applying components to selectors prevents clashes
  • We can use CPAN to distribute components
  • Files stored wherever you want

Key points

  • Final CSS is usable outside Perl world
  • Don't mix with CSS!!

Thank you

Questions?