On their website, the first feature is "Experience cleaner markup without presentational classes.", how do they solve this problem?
I think what Compass has to offer in order to allow us to create cleaner and semantic markup comes for free if you already use SASS alone.
By instance take this trivial example:
Some Mixins
#mixin box {
display: block;
}
#mixin sized_box($width:auto, $height:auto) {
#include box;
width: $width;
height: $height;
}
#mixin floated_box($direction:none, $width:auto, $height:auto) {
#include sized_box($width, $height);
float: $direction;
}
#mixin left_box($width:auto, $height:auto) {
#include floated_box(left, $width, $height);
}
#mixin right_box($width:auto, $height:auto) {
#include floated_box(right, $width, $height);
}
A Placeholder
// divs will be red
div%colored_floating {
#include left_box;
background-color: #ff0000;
}
// paragraphs will be blue
p%colored_floating {
#include right_box;
background-color: #0000ff;
}
Our stylesheet
// if #some.selector * turns out to be a div it will be red,
// and if it is a paragraph it will be blue
#some.selector *{
#extend %colored_floating;
}
Finally on your markup, you don't need any presentational classes
Except for those to make the placeholders more specific, of course.
<section id="some" class="selector">
<div>This will float and it will be red</div>
<p>But this will float right and will be blue</p>
</section>
You could always do:
// to make the placeholders absolutely generic to the whole markup,
* {
#extend %colored_floating;
}
Again, sorry for the very trivial example, but hopefully it will give you an idea on how to get rid of the presentational classes on your markup, aiming to pure semantic content.
What Compass gives us in addition is a complete framework of these mixins, placeholders and so on, ready to be used for good.
Cheers!
Related
I'm getting some strange behavior and was wondering if I am using a grid-column-row incorrectly.
I have the following HTML structure:
<div id="homeTop">
<!-- homeTop content such as headings and other nested rows and columns -->
</div>
<div id="homeMain">
<div id="homeMain-left"></div>
<div id="homeMain-right"></div>
</div>
<div id="homeBottom">
<!-- homeBottom content such as headings and other nested rows and columns -->
</div>
I then have the following SCSS to style this content:
#homeTop {
#include grid-column-row;
}
#homeMain {
#include grid-row;
}
#homeMain-left {
#include grid-column(12);
#include breakpoint(medium) {
#include grid-column(8/12);
}
}
#homeMain-right {
#include grid-column(12);
#include breakpoint(medium) {
#include grid-column(4/12);
}
}
#homeBottom {
#include grid-column-row;
}
When I view the page on a desktop-sized screen, there is one line of css that's causing the homeBottom div to float right, which is throwing off the layout. The line of CSS causing the issue is here:
#homeBottom:last-child:not(:first-child) {
float: right;
}
Since a column-row is meant to be a single element acting as a row and a column, in other words, a full width container, I'm confused why I would ever want it to have a float property. It seems that this line of CSS makes sense for columns, but not for column-rows, since the column-row behavior shouldn't depend on whether or not it's the last-child of its parent.
Is this a bug, or am I using the column-row incorrectly? I'm just trying to avoid setting homeBottom as a grid-row, and then including an extra html element inside of it just to act as a full-width grid-column. As you can see, this isn't necessary for homeTop, even though it's also using the grid-column-row mixin. This makes me think I may be using it incorrectly.
I guess another option would be to define my own my-grid-column-row mixin that includes the float declaration:
#mixin my-grid-column-row {
#include grid-column-row;
float: none !important;
}
But this seems like it shouldn't be necessary.
It looks like this is an issue with foundation:
http://github.com/zurb/foundation-sites/issues/8108
My workaround for now is to override the grid-column-row mixin with the following:
#mixin grid-column-row(
$gutter: $grid-column-gutter
) {
#include grid-row;
#include grid-column($gutter: $gutter);
float: none !important;
}
I'm using the SASS port of Bootstrap, and I'm wondering if there's any difference between using the pre-defined mixins and using SASS's #extend.
For instance, if I have:
<div class="wrapper">
Some content here....
</div>
Is there any difference between doing
.wrapper {
#include make-row();
}
and
.wrapper {
#extend .row;
}
?
If there's no difference, are there other mixins that aren't equivalent to a single #extend statement? If there aren't such mixins, why do the mixins even exist?
The big difference between #extend and a mixin is the way the css is compiled. It doesn't look like much in simple examples, but the differences and implications are significant and can be a real headache in the wild if used carelessly. #extend is a little bit like fools gold, looks great at first, but ...
Let's look at a simple example:
#extend
.row {
width: 50px;
}
.new-row {
#extend .row;
}
.another-row {
#extend .row;
}
compiles into:
.row,
.new-row,
.another-row {
width: 50px;
}
mixin
#mixin row() {
width: 50px;
}
.new-row {
#include row();
}
.another-row {
#include row();
}
compiles into:
.new-row {
width: 50px;
}
.another-row {
width: 50px;
}
A mixin includes the properties everywhere it is hit - copying them each time - whereas an #extend groups the selectors and defines the properties once. This isn't immediately obvious, because the difference is in the compiled css but it has some important implications:
Load order
With #extend the selectors will be grouped at the first point in the sass where they are encountered which can lead to some weird over-riding. If you define a selector and use #extend to bring in a property to and try to override a property defined earlier in your sass, but after the point at which the extended properties are grouped in the css then the override will not work. This can be quite perplexing.
Consider this logically ordered set of css definitions and the likely HTML: <div class='row highlight-row'></div>:
.red-text {
color: red;
}
.row {
color: green;
}
.highlight-row {
#extend .red-text;
}
compiles into:
.red-text,
.highlight-row {
color: red;
}
.row {
color: green;
}
So even though the sass ordering makes it look like the row colour would be red, the compiled css will make it green
Poor groupings
#extend can result in poorly grouped selectors in the resulting css. You can end up with thirty or forty unrelated things all sharing the same property for example. Using #extend for fonts is a good example of this.
Nesting
If you are using deeply nested sass (which is not good, btw) and you use #extend you will duplicate the fully nested selector for every #extend you use, resulting in bloated css. I've seen this a lot:
.selector-1 .selector-2 .selector-3 .selector-4,
.selector-1 .selector-2 .selector-3 .selector-4 a,
.selector-1 .selector-2 .selector-3 .selector-4 li,
.selector-1 .selector-2 .selector-3 .selector-4 td {
font-family: arial;
}
If you're new to SASS it pays to look at the compiled css.
Media queries
#extend do not work inside media queries, because media queries are not selectors.
Conclusion
My rule of thumb is to use an #extend over a mixin if you have no parameters and if you can reasonably define the #extend and share it amongst a few tightly related selectors that exist nearby in the sass, for example, in the same file that defines a sass module. Buttons are a good example of well used #extend:
%button {
padding: 10px;
}
.call-to-action {
#extend %button;
background-color: $green;
}
.submit {
#extend %button;
background-color: $grey;
}
The best article to help make the choice is here
PS, the % sign is a use of placeholder extends
I am using Compass to generate my sprites, and it is working beautifully, but I have run into one small annoyance. I am not able to include an individual sprite using the #include statement when inside of another #include, such as a media query mixin, which I commonly use. My sprite SCSS looks like this:
.sp {
background-repeat: no-repeat;
overflow: hidden;
line-height: 0;
font-size: 0;
text-indent: 100%;
border: 0;
}
$sp-sprite-dimensions: true;
$sp-sprite-base-class: '.sp';
$sprite-layout: smart;
#import "sp/*.png";
#include all-sp-sprites;
In another location, I am attempting to do this:
.logo {
a {
#include break($break1) {
#include sp-sprite(logo-small);
}
}
}
Nested #include statements are fine by SCSS, but it doesn't allow for #extend statements within #include statements, and apparently the sprite #include is generating an #extend statement behind the scenes, which I do not want. Anybody know a way around this?
EDIT:
It's been brought to my attention by #lolmaus that the real problem is that I am nesting an #extend inside of a media query. I guess that's not allowed, any way around it?
Using Compass sprites inside media queries is not possible, at least the way it's described in the documentation.
There are a couple of workarounds:
creating sprites manually via command line;
using a custom mixin.
Here's a SASS (SCSS) mixin for generating a sprite declaration block that will work with media queries
SCSS:
// http://compass-style.org/reference/compass/helpers/sprites/
#mixin get-sprite($map, $sprite, $repeat: no-repeat, $height: true, $width: true) {
//http://compass-style.org/reference/compass/helpers/sprites/#sprite-file
$sprite-image: sprite-file($map, $sprite);
// http://compass-style.org/reference/compass/helpers/sprites/#sprite-url
$sprite-map: sprite-url($map);
// http://compass-style.org/reference/compass/helpers/sprites/#sprite-position
$sprite-position: sprite-position($map, $sprite);
// Returns background
background: $sprite-map $sprite-position $repeat;
// http://compass-style.org/reference/compass/helpers/image-dimensions/
// Checks to see if the user wants height returned
#if $height == true {
// Gets the height of the sprite-image
$sprite-height: image-height($sprite-image);
// Returns the height
height: $sprite-height; }
// http://compass-style.org/reference/compass/helpers/image-dimensions/
// Checks to see if the user wants height returned
#if $width == true {
// Gets the width of the sprite-image
$sprite-width: image-width($sprite-image);
// Returns the width
width: $sprite-width; }
}
Usage:
$icons: sprite-map("sprites/icons/*.png"); // define a sprite map
// ... later
#media only screen and (max-width: 500px) {
.video .overlay {
#include get-sprite($icons, play-btn-large);
}
}
Source: GitHubGist - brubrant / get-sprite.scss
The following code describes how to do it
Gist: #extend Compass sprites in #media queries
/*
* A simple way to extend Compass sprite classes within media queries.
* Based on the knowledge gained here: http://www.sitepoint.com/cross-media-query-extend-sass/
* I admit it's nowhere near as clever, but it does work :)
*/
/*
* Set-up sprites for each media size
*/
// default
#import "icons-sm/*.png"
#include all-icons-sm-sprites
// corresponding sprites for larger devices
// notice that #import is within the #media query
// that's critical!
#media (min-width: $large)
#import "icons-lg/*.png"
#include all-icons-lg-sprites
/*
* Now you can do something like this
*/
// an example mixin
#mixin social-links($size)
$socials: facebook, twitter, youtube
#each $social in $socials
&.#{$social}
#extend .icons-#{$size}-#{$social}
/*
* Put to use
*/
// assuming you've got mark-up like this
<p class="social">
facebook
twitter
youtube
</p>
// you can do this
.social
a
#include social-links(sm)
width: 25px
height: 25px
#media (min-width: $large)
#include social-links(lg)
width: 50px
height: 50px
I have created a jsFiddle to demonstrate this issue. It's just an example.
What I'm doing
Let's say I'm making a flexible grid. My HTML looks like this:
<div>
<p>a</p>
<p>b</p>
<p>c</p>
<p>d</p>
</div>
Four columns. I have two mixins and a global variable called $gutter. In my mixin, I call this variable to add gutters and change the widths.
$gutter: 1%;
#mixin col($width){
float: left;
width: $width - ($gutter * 2);
margin: 0 $gutter;
}
#mixin row(){
width: 100%;
overflow: hidden;
}
I use it like so:
div { #include row(); }
p { #include col(25%); }
What I want to do
Now let's say I want to add a second, different grid to the page. I create this HTML and give each grid and ID to differentiate them:
<div id="one">
<p>a</p>
<p>b</p>
<p>c</p>
<p>d</p>
</div>
<div id="two">
<p>a</p>
<p>b</p>
<p>c</p>
<p>d</p>
</div>
I want the second grid to have a different gutter width. Or, alternatively, no gutters.
#one { #include row(); }
#two { #include row($gutter: 0); }
This obviously does not work. Because the number of columns can be variable, I cannot add this $gutter:0 declaration to each instance of #include col(). It breaks the DRY principle and eventually (in complicated layouts) becomes unmaintainable.
The question
How can I allow a variable set in one mixin to filter down to another (on a child element)? I am aware that I could simply do this:
#mixin row(){
width: 100%;
overflow: hidden;
.col { etc etc etc }
}
But the class name may not always be .col. Does this make sense? I want the col() mixin to inherit a variable I pass through to the row() mixin. How?
I forked the jsfiddle from Sófka and extended it with the CSS Child selector (">") to target any tags in the row.
// Inside the row mixin
& > * {
#include col($columnWidth, $gutter);
}
Furthermore I added the column width attribute to the mixin and set a default gutter.
$defaultGutter: 1% !default; // Make sure the variable is set
#mixin col($width, $gutter: $defaultGutter){
...
}
See: http://jsfiddle.net/N44LW/12/
PS.:I'm not sure if I fully understood your question, but hopefully this helps.
converting some CSS to Sass, for example:
.ptn,
.pvn,
.pan{padding-top:0px !important}
to this
#mixin ptn {padding-top:0px !important}
#mixin pvn {padding-top:0px !important}
#mixin pan {padding-top:0px !important}
but wishing i could do something more like this
#mixin ptn,
#mixin pvn,
#mixin pan {padding-top:0px !important}
is something along these lines possible?
thanks!
How about
#mixin nopadding{ padding-top:0px !important }
.ptn,
.pvn,
.pan{ #include nopadding }
?
Sass is about Reusability, so try to keep the code DRY by breaking this up into a new mixin.
Additionally you could write something like this:
#mixin nopadding{ padding-top:0px !important }
#mixin anothermixin{ #include nopadding; ... }
normalselector{ #include anothermixin; }
Alternatively you can use the #extend feature to be a little cleaner, depending on your purposes.
So if you have:
.ptn { padding-top:0px !important; }
You can do this anywhere else in your code (it doesn't require it to go after for scoping purposes, like mixins do):
.pvn { #extend .ptn; /* pvn-specific rules can still go here */ }
.pan { #extend .ptn; /* pan-specific rules can still go here */}
This will output as such:
.ptn, .pvn, .pan { padding-top:0px !important; }
.pvn { /* pvn-specific rules can still go here */ }
.pan { /* pan-specific rules can still go here */ }
This can be a cleaner output than using mixins, which would duplicate the code. This is particularly useful for larger blocks of code, like clear fixes. But mixins do have their place.
Speaking of things having their place… is that !important really necessary? ;-)