Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
OOSASS: Writting OOP-like CSS Component (Factory, Accessor, Dependency Injection etc.) #sass
<h2>list</h2>
<ul class="list">
<li class="list\item">Item</li>
<li class="list\item">Item</li>
</ul>
<h2>note-list</h2>
<ul class="note-list">
<li class="note-list\item">Item</li>
<li class="note-list\item">Item</li>
</ul>
// ----
// Sass (v3.4.9)
// Compass (v1.0.1)
// ----
// OOSASS: Writting OOP-like CSS Component (Factory, Accessor, Dependency Injection etc.)
//
// Other ideas
// https://github.com/whizark/xass#ideas
//
// @author Whizark
// In this example, I use `/` (back-slash) as namespace separator
// for HTML, Sass and CSS.
//
// See also: Sass Naming Convention
// https://gist.github.com/whizark/803834304d0ff34e99af
//
// See also: HTML/CSS Class Naming Convention
// https://gist.github.com/whizark/92ed70d90d262a44db84
//
// See also: Using back-slash as the namespace separator in HTML/CSS
// https://gist.github.com/whizark/ea2ba0ff3f47956fda0f
// ================================
// List Item Class (not HTML class)
// ================================
// Factory(constructor) for `List Item` class
@function list-item\new($classname, $color: inherit) {
// Returns property Map
@return (
name: 'list-item', // Class name (you may internally use this)
classname: $classname, // HTML Class name
color: $color // List item color (this is just an example)
);
}
// Accessor(getter) for `name` property
@function list-item\get-name($instance) {
@return map-get($instance, 'name');
}
// Accessor(getter) for `classname` property
@function list-item\get-classname($instance) {
@return map-get($instance, 'classname');
}
// Accessor(getter) for `color` property
@function list-item\get-color($instance) {
@return map-get($instance, 'color');
}
// ================================
// List Class (not HTML class)
// A collection class of `List Item`
// ================================
// Factory(constructor) for `List` class
@function list\new($classname, $list-item, $spacing: 1em, $list-style: disc) {
@return (
name: 'list', // Class name (you may internally use this)
classname: $classname, // HTML Class name
list-item: $list-item, // Instance of `List Item` class (a dependency)
spacing: $spacing, // Spacing (this is just an example)
list-style: $list-style // Spacing (this is just an example)
);
}
// Accessor(getter) for `name` property
@function list\get-name($instance) {
@return map-get($instance, 'name');
}
// Accessor(getter) for `classname` property
@function list\get-classname($instance) {
@return map-get($instance, 'classname');
}
// Accessor(getter) for `list-item` property
@function list\get-list-item($instance) {
@return map-get($instance, 'list-item');
}
// Accessor(getter) for `spacing` property
@function list\get-spacing($instance) {
@return map-get($instance, 'spacing');
}
// Accessor(getter) for `list-style` property
@function list\get-list-style($instance) {
@return map-get($instance, 'list-style');
}
// ====================
// List Component (API)
// ====================
// This is just a *simple* example using class.
@mixin component\list($list) {
// Gets the instance of the `List Item` class that is a dependency.
$list-item: list\get-list-item($list);
// CSS class selector for `List Item`
.#{list-item\get-classname($list-item)} {
// The `spacing` property that belongs to `List` class
// adjusts `List Item` margin,
// because the margin is/should be coordinated by `List` (collection) class
// and `List Item` does'nt/shouldn't know its own margin.
margin-left: list\get-spacing($list);
color: list-item\get-color($list-item);
// You may mixin/delegate something by/to a Mixin/Function of `List Item` class.
// Ofcource mixin/delegation is more better way.
//
// e.g. @include list-item\color($color);
// or
// color: list-item\color($color);
}
// CSS class selector for List
.#{list\get-classname($list)} {
list-style: list\get-list-style($list);
margin: 0;
padding: 0;
}
}
// ========
// Use case
// ========
// Creates a generic list item
$generic-list-item: list-item\new(
// Note: `\` (back-slash) should be escaped by `\` within string literal.
'list\\\\item'
);
// Creates a generic list
$generic-list: list\new(
'list',
$list-item: $generic-list-item, // Injects generic list item (Dependency Injection)
$spacing: 2em
);
// Creates a note list item
$note-list-item: list-item\new(
'note-list\\\\item',
$color: gray
);
// Creates a note list
$note-list: list\new(
'note-list',
$list-item: $note-list-item, // Injects note list item (Dependency Injection)
$list-style: circle,
$spacing: 1em
);
// Includes components
@include component\list($generic-list);
@include component\list($note-list);
.list\\item {
margin-left: 2em;
color: inherit;
}
.list {
list-style: disc;
margin: 0;
padding: 0;
}
.note-list\\item {
margin-left: 1em;
color: gray;
}
.note-list {
list-style: circle;
margin: 0;
padding: 0;
}
<h2>list</h2>
<ul class="list">
<li class="list\item">Item</li>
<li class="list\item">Item</li>
</ul>
<h2>note-list</h2>
<ul class="note-list">
<li class="note-list\item">Item</li>
<li class="note-list\item">Item</li>
</ul>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment