Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Leveraging a meta-framework #10

Closed
scottkellum opened this Issue · 13 comments

2 participants

@scottkellum

Thoughts on using a meta-framework like Compass to manage this modular structure? Seems kind of hard to manage as lots of little flat CSS files when tools like Compass exist precisely for architectures like this.

Also, the extension system for Compass would allow for easy module swapping, configuration, and theming. For example, maybe I want to use your typography module with another grid system like Susy or Singularity. No need to have separate production CSS either as Compass can handle concatenation and compression for production.

@jslegers
Owner

Improved maintenance and customisation by means of a pre-processor language is one of the features I'm planning to include with a future release of Cascade Framework. I'm currently still figuring out whether to pick LESS or SASS.

As my backend background is in PHP, I intend to use Assetic ( https://github.com/kriswallsmith/assetic ) for compiling and minifying the LESS or SASS ( Assetic supports both ). I'm not inclined to use Compass because I don't want to have Ruby as a depencency, although I will definitely look at the architecture of Compass for inspiration.

@scottkellum

LESS is abandonware if that helps your decision… Also not very powerful/well thought out features. Preprocessors by themselves aren’t meta-frameworks because they don’t have the extension management stuff Compass has.

@jslegers
Owner

@ scottkellum :

I'd rather write a meta-framework myself that's not dependent on Ruby or any other backend language.

In fact, Cascade Framework was conceived as a frontend layer of a PHP based backend UI framework yet to be built. A platform independent SASS-based meta-framework inspired by Compass sounds like an interesting intermediate step.

@jslegers
Owner

I'm currently experimenting with SASS 3.2.

It looks very promising and I expect to release a SASS version with Cascade Framework 2.

@scottkellum

btw it’s Sass not SASS

@jslegers
Owner

Thanks for the tip ;-)

What you do think of the following design pattern?

%displayblock {
        display: block;
        *zoom:1;
}
%clearboth {
        clear: both;
}
%blankastable {
        display: table;
        content: "";
}
%floatleft {
        float: left;
}
%widthfull {
        width: 100%;
}
%initborder {
        border: 0 solid #ccc;
}
%bordertopleft {
        border-width: 1px 0 0 1px;
}
%borderbottomright {
        border-width: 0 1px 1px 0;
}
%clearfix {
        @extend %displayblock;
        &:before {
                @extend %blankastable;
        }
        &:after {
                @extend %blankastable;
                @extend %clearboth;
        }
}
div {
        @extend %clearfix;
        @extend %initborder;
}
td {
        @extend %initborder;
}
th {
        @extend %initborder;
}
table {
        @extend %initborder;
        @extend %widthfull;
        &.border {
                @extend %bordertopleft;
                & td {
                        @extend %borderbottomright;
                }
                & th {
                        @extend %borderbottomright;
                }
        }
}
.col {
        @extend %floatleft;
        @extend %widthfull;
}

This would generate the following css code :

div {
        display: block;
        *zoom: 1; }

div:after {
        clear: both; }

div:before, div:after {
        display: table;
        content: ""; }

.col {
        float: left; }

table, .col {
        width: 100%; }

div, td, th, table {
        border: 0 solid #ccc; }

table.border {
        border-width: 1px 0 0 1px; }

table.border td, table.border th {
        border-width: 0 1px 1px 0; }
@scottkellum

Silent selectors are amazing to consolidate repeated chunks of code but scaling up small chunks like this can result in selector bloat. I tend to use repetition of styles because they gzip better as the site grows. There are definitely places to use silent selectors like extending/modifying objects is a great place to use them.

.button {
  // button styles
}

.button-big {
  @extend .button;
  font-size: 2em;
}

clearfixes are something I use fairly often:

%clearfix {
  // clearfix
}
@jslegers
Owner

Actually, I found that consolidating repeated rules into units of three rules of less (and typically one just one rule) results in the smallest footprint, regardless of whether you minify and/or gzip.

Check out the following grouping strategies of the same CSS rules below and notice how grouping by singular CSS rules leads to progressively better footprints. I'm using an online version of the YUI Compressor at http://refresh-sf.com/yui/ for the calculations.

Here's an overview of the footprints :

Example 1 :

before  8771
after compression   5510
compression ratio   37%
after compression and gzip  1017
compression and gzip ratio  88%

Example 2 :

before  5158
after compression   3557
compression ratio   31%
after compression and gzip  703
compression and gzip ratio  86%

Example 3 :

before  2037
after compression   1806
compression ratio   11%
after compression and gzip  602
compression and gzip ratio  70%

Example 4

before  1841
after compression   1712
compression ratio   7%
after compression and gzip  587
compression and gzip ratio  68%

And now the actual code :

Example 1 :

div {
    *zoom:1;
}

article {
    *zoom:1;
}

aside {
    *zoom:1;
}

details {
    *zoom:1;
}

figcaption {
    *zoom:1;
}

figure {
    *zoom:1;
}

footer {
    *zoom:1;
}

header {
    *zoom:1;
}

hgroup {
    *zoom:1;
}

nav {
    *zoom:1;
}

section {
    *zoom:1;
}

pre {
    *zoom:1;
}

.nav {
    *zoom:1;
}

.nav a {
    *zoom:1;
}

.sizefill {
    *zoom:1;
}

.sizefit img {
    *zoom:1;
}

blockquote small {
    *zoom:1;
}

address {
    *zoom:1;
}

button {
    *zoom:1;
}

.button {
    *zoom:1;
}

.nav ul {
    *zoom:1;
}

.nav li {
    *zoom:1;
}

.logo {
    *zoom:1;
}

div {
    display:block;
}

article {
    display:block;
}

aside {
    display:block;
}

details {
    display:block;
}

figcaption {
    display:block;
}

figure {
    display:block;
}

footer {
    display:block;
}

header {
    display:block;
}

hgroup {
    display:block;
}

nav {
    display:block;
}

section {
    display:block;
}

pre {
    display:block;
}

.nav {
    display:block;
}

.nav a {
    display:block;
}

.sizefill {
    display:block;
}

.sizefit img {
    display:block;
}

blockquote small {
    display:block;
}

address {
    display:block;
}

button {
    display:block;
}

.button {
    display:block;
}

.nav ul {
    display:block;
}

.nav li {
    display:block;
}

.logo {
    display:block;
}

figcaption {
    clear:both;
}

div:after {
    clear:both;
}

article:after {
    clear:both;
}

aside:after {
    clear:both;
}

details:after {
    clear:both;
}

figcaption:after {
    clear:both;
}

figure:after {
    clear:both;
}

footer:after {
    clear:both;
}

header:after {
    clear:both;
}

hgroup:after {
    clear:both;
}

nav:after {
    clear:both;
}

section:after {
    clear:both;
}

pre:after {
    clear:both;
}

.nav:after {
    clear:both;
}

.nav a:after {
    clear:both;
}

.sizefill:after {
    clear:both;
}

.sizefit img:after {
    clear:both;
}

blockquote small:after {
    clear:both;
}

address:after {
    clear:both;
}

button:after {
    clear:both;
}

.button:after {
    clear:both;
}

.nav ul:after {
    clear:both;
}

.nav li:after {
    clear:both;
}

div:after {
    display:table;
}

article:after {
    display:table;
}

aside:after {
    display:table;
}

details:after {
    display:table;
}

figcaption:after {
    display:table;
}

figure:after {
    display:table;
}

footer:after {
    display:table;
}

header:after {
    display:table;
}

hgroup:after {
    display:table;
}

nav:after {
    display:table;
}

section:after {
    display:table;
}

pre:after {
    display:table;
}

.nav:after {
    display:table;
}

.nav a:after {
    display:table;
}

.sizefill:after {
    display:table;
}

.sizefit img:after {
    display:table;
}

blockquote small:after {
    display:table;
}

address:after {
    display:table;
}

button:after {
    display:table;
}

.button:after {
    display:table;
}

.nav ul:after {
    display:table;
}

.nav li:after {
    display:table;
}

div:before {
    display:table;
}

article:before {
    display:table;
}

aside:before {
    display:table;
}

details:before {
    display:table;
}

figcaption:before {
    display:table;
}

figure:before {
    display:table;
}

footer:before {
    display:table;
}

header:before {
    display:table;
}

hgroup:before {
    display:table;
}

nav:before {
    display:table;
}

section:before {
    display:table;
}

pre:before {
    display:table;
}

.nav:before {
    display:table;
}

.nav a:before {
    display:table;
}

.sizefill:before {
    display:table;
}

.sizefit img:before {
    display:table;
}

blockquote small:before {
    display:table;
}

address:before {
    display:table;
}

button:before {
    display:table;
}

.button:before {
    display:table;
}

.nav ul:before {
    display:table;
}

.nav li:before {
    display:table;
}

div:after {
    content:"";
}

article:after {
    content:"";
}

aside:after {
    content:"";
}

details:after {
    content:"";
}

figcaption:after {
    content:"";
}

figure:after {
    content:"";
}

footer:after {
    content:"";
}

header:after {
    content:"";
}

hgroup:after {
    content:"";
}

nav:after {
    content:"";
}

section:after {
    content:"";
}

pre:after {
    content:"";
}

.nav:after {
    content:"";
}

.nav a:after {
    content:"";
}

.sizefill:after {
    content:"";
}

.sizefit img:after {
    content:"";
}

blockquote small:after {
    content:"";
}

address:after {
    content:"";
}

button:after {
    content:"";
}

.button:after {
    content:"";
}

.nav ul:after {
    content:"";
}

.nav li:after {
    content:"";
}

div:before {
    content:"";
}

article:before {
    content:"";
}

aside:before {
    content:"";
}

details:before {
    content:"";
}

figcaption:before {
    content:"";
}

figure:before {
    content:"";
}

footer:before {
    content:"";
}

header:before {
    content:"";
}

hgroup:before {
    content:"";
}

nav:before {
    content:"";
}

section:before {
    content:"";
}

pre:before {
    content:"";
}

.nav:before {
    content:"";
}

.nav a:before {
    content:"";
}

.sizefill:before {
    content:"";
}

.sizefit img:before {
    content:"";
}

blockquote small:before {
    content:"";
}

address:before {
    content:"";
}

button:before {
    content:"";
}

.button:before {
    content:"";
}

.nav ul:before {
    content:"";
}

.nav li:before {
    content:"";
}

section {
    border:0 solid #ccc;
}

article {
    border:0 solid #ccc;
}

header {
    border:0 solid #ccc;
}

footer {
    border:0 solid #ccc;
}

aside {
    border:0 solid #ccc;
}

nav {
    border:0 solid #ccc;
}

div {
    border:0 solid #ccc;
}

table {
    border:0 solid #ccc;
}

col {
    border:0 solid #ccc;
}

th {
    border:0 solid #ccc;
}

td {
    border:0 solid #ccc;
}

img {
    border:0 solid #ccc;
}

figure {
    border:0 solid #ccc;
}

fieldset {
    border:0 solid #ccc;
}

pre {
    border:0 solid #ccc;
}

code {
    border:0 solid #ccc;
}

abbr {
    border:0 solid #ccc;
}

span {
    border:0 solid #ccc;
}

ol {
    border:0 solid #ccc;
}

ul {
    border:0 solid #ccc;
}

li {
    border:0 solid #ccc;
}

a {
    border:0 solid #ccc;
}

button {
    border:0 solid #ccc;
}

input {
    border:0 solid #ccc;
}

hr {
    border:0 solid #ccc;
}

select {
    border:0 solid #ccc;
}

textarea {
    border:0 solid #ccc;
}

blockquote {
    border:0 solid #ccc;
}

td input {
    border:0 solid #ccc;
}

.icon-border {
    border:0 solid #ccc;
}

.checkbox {
    border:0 solid #ccc;
}

.radio {
    border:0 solid #ccc;
}

.datasheet table.body {
    border:0 solid #ccc;
}

section {
    float:left;
}

article {
    float:left;
}

header {
    float:left;
}

footer {
    float:left;
}

aside {
    float:left;
}

nav {
    float:left;
}

img {
    float:left;
}

.nav {
    float:left;
}

.col {
    float:left;
}

.tabs {
    float:left;
}

.tab-content {
    float:left;
}

.sizefit {
    float:left;
}

.nav li {
    float:left;
}

button {
    float:left;
}

.button {
    float:left;
}

.button-group {
    float:left;
}

.nav a {
    float:left;
}

.left li li {
    float:left;
}

.tabs .left {
    float:left;
}

.right li li {
    float:left;
}

section {
    min-height:1px;
}

article {
    min-height:1px;
}

header {
    min-height:1px;
}

footer {
    min-height:1px;
}

aside {
    min-height:1px;
}

nav {
    min-height:1px;
}

.col {
    min-height:1px;
}

.tabs {
    min-height:1px;
}

section {
    width:100%;
}

article {
    width:100%;
}

header {
    width:100%;
}

footer {
    width:100%;
}

aside {
    width:100%;
}

nav {
    width:100%;
}

.site-footer {
    width:100%;
}

.site-header {
    width:100%;
}

table {
    width:100%;
}

.col {
    width:100%;
}

.tabs {
    width:100%;
}

.tab-content {
    width:100%;
}

.tabs .nav {
    width:100%;
}

figure img {
    width:100%;
}

.tree li {
    width:100%;
}

Example 2 :

figcaption {
    clear:both;
}

div:after {
    clear:both;
}

article:after {
    clear:both;
}

aside:after {
    clear:both;
}

details:after {
    clear:both;
}

figcaption:after {
    clear:both;
}

figure:after {
    clear:both;
}

footer:after {
    clear:both;
}

header:after {
    clear:both;
}

hgroup:after {
    clear:both;
}

nav:after {
    clear:both;
}

section:after {
    clear:both;
}

pre:after {
    clear:both;
}

.nav:after {
    clear:both;
}

.nav a:after {
    clear:both;
}

.sizefill:after {
    clear:both;
}

.sizefit img:after {
    clear:both;
}

blockquote small:after {
    clear:both;
}

address:after {
    clear:both;
}

button:after {
    clear:both;
}

.button:after {
    clear:both;
}

.nav ul:after {
    clear:both;
}

.nav li:after {
    clear:both;
}

div:after, div:before {
    content:""; display:table;
}

article:after, article:before {
    content:""; display:table;
}

aside:after, aside:before {
    content:""; display:table;
}

details:after, details:before {
    content:""; display:table;
}

figcaption:after, figcaption:before {
    content:""; display:table;
}

figure:after, figure:before {
    content:""; display:table;
}

footer:after, footer:before {
    content:""; display:table;
}

header:after, header:before {
    content:""; display:table;
}

hgroup:after, hgroup:before {
    content:""; display:table;
}

nav:after, nav:before {
    content:""; display:table;
}

section:after, section:before {
    content:""; display:table;
}

pre:after, pre:before {
    content:""; display:table;
}

.nav:after, .nav:before {
    content:""; display:table;
}

.nav a:after, .nav a:before {
    content:""; display:table;
}

.sizefill:after, .sizefill:before {
    content:""; display:table;
}

.sizefit img:after, .sizefit img:before {
    content:""; display:table;
}

blockquote small:after, blockquote small:before {
    content:""; display:table;
}

address:after, .address:before {
    content:""; display:table;
}

button:after, button:before {
    content:""; display:table;
}

.button:after, .button:before {
    content:""; display:table;
}

.nav ul:after, .nav ul:before {
    content:""; display:table;
}

.nav li:after, .nav li:before {
    content:""; display:table;
}

figcaption {
    display:block;*zoom:1;
}

hgroup {
    display:block;*zoom:1;
}

.nav {
    display:block;*zoom:1;
}

.nav a {
    display:block;*zoom:1;
    float:left;
}

.sizefill {
    display:block;*zoom:1;
}

.sizefit img {
    display:block;*zoom:1;
}

blockquote small {
    display:block;*zoom:1;
}

.button {
    display:block;*zoom:1;
}

.nav ul {
    display:block;*zoom:1;
}

.nav li {
    display:block;*zoom:1;
}

.logo {
    display:block;*zoom:1;
}

details {
    display:block;*zoom:1;
}

address {
    display:block;*zoom:1;
}

nav {
    border:0 solid #ccc;
    display:block;*zoom:1;
}

div {
    border:0 solid #ccc;
    display:block;*zoom:1;
}

table {
    border:0 solid #ccc;
}

.col {
    border:0 solid #ccc;
}

th {
    border:0 solid #ccc;
}

td {
    border:0 solid #ccc;
}

img {
    border:0 solid #ccc;
}

fieldset {
    border:0 solid #ccc;
}

pre {
    border:0 solid #ccc;
    display:block;*zoom:1;
}

code {
    border:0 solid #ccc;
}

abbr {
    border:0 solid #ccc;
}

span {
    border:0 solid #ccc;
}

ol {
    border:0 solid #ccc;
}

ul {
    border:0 solid #ccc;
}

li {
    border:0 solid #ccc;
}

a {
    border:0 solid #ccc;
}

button {
    border:0 solid #ccc;
    display:block;*zoom:1;
}

input {
    border:0 solid #ccc;
}

hr {
    border:0 solid #ccc;
}

select {
    border:0 solid #ccc;
}

textarea {
    border:0 solid #ccc;
}

blockquote {
    border:0 solid #ccc;
}

td input {
    border:0 solid #ccc;
}

.icon-border {
    border:0 solid #ccc;
}

.checkbox {
    border:0 solid #ccc;
}

.radio {
    border:0 solid #ccc;
}

.datasheet table.body {
    border:0 solid #ccc;
}

figure {
    border:0 solid #ccc;
    display:block;*zoom:1;
}

section,article,header,footer,aside {
    border:0 solid #ccc;
    display:block;*zoom:1;
    float:left;
    min-height:1px;
    width:100%;
}

nav, .col, .tabs {
    float:left;
    min-height:1px;
    width:100%;
}

img {
    float:left;
}

.nav {
    float:left;
}

.tab-content {
    float:left;
}

.sizefit {
    float:left;
}

.nav li {
    float:left;
}

button {
    float:left;
}

.button {
    float:left;
}

.button-group {
    float:left;
}

.left li li {
    float:left;
}

.tabs .left {
    float:left;
}

.right li li {
    float:left;
}

.site-footer {
    width:100%;
}

.site-header {
    width:100%;
}

table {
    width:100%;
}

.tab-content {
    width:100%;
}

.tabs .nav {
    width:100%;
}

figure img {
    width:100%;
}

.tree li {
    width:100%;
}

Example 3 :

figcaption,div:after,article:after,aside:after,details:after,figcaption:after,figure:after,footer:after,header:after,hgroup:after,nav:after,section:after,pre:after,.nav:after,.nav a:after,.sizefill:after,.sizefit img:after,blockquote small:after,address:after,button:after,.button:after,.nav ul:after,.nav li:after {
    clear:both;
}

div:after, div:before,article:after, article:before,aside:after, aside:before,details:after, details:before,figcaption:after, figcaption:before,figure:after, figure:before,footer:after, footer:before,header:after, header:before,hgroup:after, hgroup:before,nav:after, nav:before,section:after, section:before,pre:after, pre:before,.nav:after, .nav:before,.nav a:after, .nav a:before,.sizefill:after, .sizefill:before,.sizefit img:after, .sizefit img:before,blockquote small:after, blockquote small:before,address:after, .address:before,button:after, button:before,.button:after, .button:before,.nav ul:after, .nav ul:before,.nav li:after, .nav li:before {
    content:""; display:table;
}

figcaption,hgroup,.nav, .sizefill,.sizefit img,blockquote small,.button,.nav ul,.nav li,.logo,details,address {
    display:block;*zoom:1;
}

.nav a {
    display:block;*zoom:1;
    float:left;
}

nav,div,pre,button {
    border:0 solid #ccc;
    display:block;*zoom:1;
}

table,.col,th,td,img,fieldset,code,abbr,span,ol,ul,li,a,input,hr,select,textarea,blockquote,td input,.icon-border,.checkbox,.radio,.datasheet table.body {
    border:0 solid #ccc;
}

figure {
    border:0 solid #ccc;
    display:block;*zoom:1;
}

section,article,header,footer,aside {
    border:0 solid #ccc;
    display:block;*zoom:1;
    float:left;
    min-height:1px;
    width:100%;
}

nav, .col, .tabs {
    float:left;
    min-height:1px;
    width:100%;
}

img,.nav,.tab-content,.sizefit,.nav li,button,.button,.button-group,.left li li,.tabs .left,.right li li {
    float:left;
}

.site-footer,.site-header,table,.tab-content,.tabs .nav,figure img,.tree li {
    width:100%;
}

Example 4 :

div,article,aside,details,figcaption,figure,footer,header,hgroup,nav,section,pre,.nav,.nav a,.sizefill,.sizefit img,blockquote 

small,address,button,.button,.nav ul,.nav li,.logo {
    display:block;*zoom:1;
}

figcaption,div:after,article:after,aside:after,details:after,figcaption:after,figure:after,footer:after,header:after,
hgroup:after,nav:after,section:after,pre:after,.nav:after,.nav a:after,.sizefill:after,.sizefit img:after,
blockquote small:after,address:after,.nav ul:after,.nav li:after {
    clear:both;
}


div:before,div:after,article:before,article:after,aside:before,aside:after,details:before,details:after,
figcaption:before,figcaption:after,figure:before,figure:after,footer:before,footer:after,
header:before,header:after,hgroup:before,hgroup:after,nav:before,nav:after,section:before,section:after,
pre:before,pre:after,.nav:before,.nav:after,.nav a:before,.nav a:after,.sizefill:before,.sizefill:after,
.sizefit img:before,.sizefit img:after,blockquote small:before,blockquote small:after,address:before,address:after,
.nav ul:before,.nav ul:after,.nav li:before,.nav li:after {
    content:""; display:table;
}

section,article,header,footer,aside,nav,div,table,.col,th,td,img,figure,fieldset,pre,code,abbr,span,ol,ul,li,a,button,input,hr,s

elect,textarea,blockquote,td input,.icon-border,.checkbox,.radio,.datasheet table.body {
    border:0 solid #ccc;
}

section,article,header,footer,aside,nav,img,.nav,.col,.tabs,.tab-content,.sizefit,.nav li,button,.button,.button-group,.nav 

a,.left li li,.tabs .left,.right li li {
    float:left;
}

section,article,header,footer,aside,nav,.col,.tabs {
    min-height:1px;
}

section,article,header,footer,aside,nav,.site-footer,.site-header,table,.col,.tabs,.tab-content,.tabs .nav,figure img,.tree li {
    width:100%;
}
@scottkellum

Honestly I don’t care too much how you do things as long as it is maintainable. In real-world examples I usually find mixins tend to be easier to work with and compress really well when written well. As things start to nest deeper selector bloat happens. IE also has a selector limit of 4096 and it is pretty easy to hit that when working this way.

This thread is getting totally off topic of the meta-framework discussion. Sounds like you don’t plan on going that way. I am going to close this. If you would like Sass help I suggest #sass on irc.freenode.net.

@jslegers jslegers reopened this
@jslegers
Owner

I'm currently working on a Sass version of Cascade Framework Light, using a design pattern similar to the one I described.

I see the Cascade Framework Light as a proof-of-concept for the Cascade Framework version. A Sass version of Cascade Framework will be implemented once the Cascade Framework Light version has been finetuned.

@scottkellum

not sure how a Sass version relates to meta-frameworking issue. Are you planning on breaking the framework down into smaller components and releasing through Compass/Bower? Because that is what this issue is about.

@jslegers jslegers reopened this
@jslegers
Owner

The idea is to have a layered component model with varying levels of complexity, similar to well-written OO code..

The first release will contain just a single SCSS file with a whole range of configurable parameters.

I'm not planning to include Compass in this stage, but the code should be fully compatible with Compass or any other Sass implementation.

@jslegers
Owner

Cascade Framework 2 is currently under development and will be based on a custom meta-framework that uses some of the latest features in Sass 3.3. It will be written in Sass only and not rely on Compass or Bower to allow compatibility with non-Ruby implementations of Sass 3.3+.

@jslegers jslegers closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.