Sass multi-state navigation bar issue - sass

I have a navigation bar, where the buttons have a hover state but also need to be "active" on their respective page. Since this navigation bar is part of an include, I decided to do the active state via a class on the body tag, as in .dashboard .dashboard-button. So I have the hover and this.
I was trying to figure out the most streamlined way to do this with Sass/Compass. I created a couple of mixins:
#mixin nav-button-on($icon) {
background-color: #2f3684; // Old browsers
#include filter-gradient($offwhite, #E5E5E5, vertical); // IE6-9
#include background-image(url('../images/'+$icon+'-on.png'),linear-gradient(top, $offwhite 0%, #E5E5E5 100%));
border-bottom: $borderbottom solid #F31A35;
a { color: $red;}
}
#mixin nav-button($icon){
background-color: #fff; // Old browsers
#include filter-gradient(#fff, #fff, vertical); // IE6-9
#include background-image(url('../images/'+$icon+'.png'),linear-gradient(top, #fff 0%, #fff 100%));
}
And then in the LI where the buttons are defined, I have
li {
&.dashboard {
#include nav-button('dashboard');
}
.dashboard &.dashboard {
#include nav-button-on('dashboard');
&:hover {
#include nav-button-on('dashboard');
}
}
}
HTML:
<body class="dashboard">
<div id="nav">
<ul>
<li class="first dashboard">Dashboard</li>
<li class="challenges">Challenges & Teams</li>
<li class="goals">Goals</li>
<li class="activity">My Activity</li>
<li class="destinations">Destinations</li>
<li class="fitness last">Fitness Resources</li>
</ul>
</div>
This seems a bit convoluted, I was wondering if anyone had any advice to streamline this at all.
NOTE: I had to add the white-to-white gradient, since when hovering over a solid-color background with the gradient hover state caused a flash.

There are a number of things to improve here:
Are you really dealing with that hierarchy of dashboard classes? For example, you're currently compiling to:
li.dashboard {
...
}
li .dashboard li.dashboard {
...
}
This seems wrong or at least poorly structured. Perhaps you could simplify things here.
Assuming you need this for each of your nav <li> elements, DRY it up with an iterated mixin:
li {
#each $item in dashboard, challenges, goals, activity, destinations, fitness {
&.#{$item} {
#include nav-button($item);
}
.#{$item} &.#{$item} {
#include nav-button-on($item);
&:hover {
#include nav-button-on($item);
}
}
}
}
But #2 is not actually the best way. Use placeholders rather than mixins for this kind of stuff, or combine the two. I'd do something like this:
%nav-button {
background-color: #fff; // Old browsers
#include filter-gradient(#fff, #fff, vertical); // IE6-9
}
%nav-button-on {
background-color: #2f3684; // Old browsers
#include filter-gradient($offwhite, #E5E5E5, vertical); // IE6-9
border-bottom: $borderbottom solid #F31A35;
a { color: $red;}
}
#mixin li-image($icon) {
#include background-image(url('../images/'+$icon+'.png'),linear-gradient(top, #fff 0%, #fff 100%));
}
#mixin li-image-on($icon) {
#include background-image(url('../images/'+$icon+'-on.png'),linear-gradient(top, $offwhite 0%, #E5E5E5 100%));
}
#each $item in dashboard, challenges, goals, activity, destinations, fitness {
body.#{$item} li, li.#{$item}:hover {
#extend %nav-button-on;
#include li-image-on($item);
}
li.#{$item} {
#extend %nav-button;
#include li-image($item);
}
}
Compare the outputs and maintainability of these and I think you'll find this quite a bit more streamlined!

You have a wrong } after #include nav-button('dashboard');
try it:
li {
&.dashboard {
#include nav-button('dashboard');
.dashboard &.dashboard {
#include nav-button-on('dashboard');
&:hover {
#include nav-button-on('dashboard');
}
}
}
}

Related

If mixins in empty show default

Is it possible to have a mixin that can override a current code block? I want to have it so that if the #mixin is empty the background for the box would be empty and then show in orange, but when I remove the #mixin it does not change to orange? What am I doing wrong?
#mixin box {
background: red;
}
.box {
#if box {
#include box;
} #else {
background: orange;
}
}
The $color: null is just for setting a value if you didn't pass a value for your #mixin. after that you can check easily inside your #mixin using #if #else.
Sass
#mixin background-color($color: null) {
#if($color) {
background-color: $color;
} #else {
background-color: orange;
}
};
h1 {
#include background-color(red);
}
h2 {
#include background-color(green);
}
h3 {
#include background-color();
}
h4{
#include background-color(blue)
}
Html
<h1>color</h1>
<h2>color 2</h2>

Is it possible to compile only mixins in scss?

I have a scss file with some partial mixins. I want to compile only that mixin, without converting it to CSS. Let me show you the code.
#mixin baseButton() {
position: relative;
display: inline-block;
&:disabled {
background-color: gray;
}
}
#mixin button($classname:".midori-button") {
#{$classname} {
color: gray;
#include baseButton();
}
}
#include button();
Is it possible compile this code into SCSS like the above but not into CSS like:
.midori-button {
color: gray;
position: relative;
display: inline-block;
&:disabled {
background-color: gray;
}
}
Thanks.
P.S: Not native.
Not sure if I'm reading this question right but you can create mixin partials that does not render CSS by adding an underscore to the file name like _button.scss
If you do that you should place the #inclue in the file/files you want to render CSS (using #import to make the mixins available).
// _button.scss => No CSS
#mixin baseButton(){ ... }
#mixin button(){ ...}
// module-1.scss => module-1.css
#import '_button.scss';
#include baseButton;
#include button;
// module-2.scss => module-2.css
#import '_button.scss';
#include baseButton;
#include button;

SASS Mixin: only apply hover style if class is on a link?

I'm attempting to set a bunch of background colours using a mixin. I'd also like to apply hover styling to these background colours IF the classes are assigned to a link element:
#mixin bg-color($color) {
background-color: $color;
&[ifthisisalink] {
&:hover {
background-color: darken($color, 10%);
}
}
}
.bg-blue {
#include bg-color(blue);
}
So if we have .bg-blue on a plain div, there is no hover color. But if .bg-blue is on a link, there is a hover color:
<div class="bg-blue">Hover on me and nothing happens.</div>
Hover on me and I go darker.
Is this possible in SASS?
You need #at-root:
#mixin bg-color($color) {
background-color: $color;
#at-root {
a#{&} {
&:hover {
background-color: darken($color, 10%);
}
}
}
}
.bg-blue {
#include bg-color(blue);
}

Not last child mixin SASS

Is it possible to turn this:
.redstripe p:not(last-child) {
border-bottom:1px solid red;
}
Into a mixin so that I can apply it to any element and assign a child tag to it like:
#mixin redstripe (this.$children):not(last-child) {
border-bottom:1px solid red;
}
And then apply:
div {
#include redstripe(p);
}
What is the correct way to implement this?
Here's a general purpose mixin like you've described.
DEMO
#mixin not-last-child($selector) {
& #{$selector}:not(:last-child) {
#content;
}
}
We can pass it a selector string to use.
SCSS:
.thing {
#include not-last-child('p') {
color: red;
}
}
CSS:
.thing p:not(:last-child) {
color: red;
}
Sass Documentation

Susy grid - any (easy?) way to make 'columns' the same height?

Getting my feet wet with Susy/sass/haml etc (using adjusted middleman - with latest susy from master branch)
Have this in grid.css.scss
#import 'susy';
$total-columns : 8;
$column-width : 4em;
$gutter-width : 0em;
$grid-padding : $gutter-width;
$break-max : 12;
$container-style: magic;
// Container
.page {
#include container($total-columns, $break-max);
}
// Layout
.header {
#include at-breakpoint($break-max) {
#include pad(1,1);
}
}
.pagenav {
clear: both;
#include at-breakpoint($break-max) {
#include pad(1,1);
}
}
.main {
clear: both;
.main-left {
#include span-columns($total-columns omega);
#include at-breakpoint(10) {
#include span-columns(7);
}
}
.main-right {
#include span-columns($total-columns omega);
#include at-breakpoint(10) {
#include span-columns(3 omega);
}
}
#include at-breakpoint($break-max) {
#include pad(1,1);
}
}
.footer {
clear: both;
#include at-breakpoint($break-max) {
#include pad(1,1);
}
}
this snippet comes from site.css.scss
.main {
background-color: #eee;
}
.main-left {
background-color: #fff;
}
.main-right {
background-color: #eee;
}
.body background is black...
Now when content in main-left is larger than main-right I see a black square on the bottom right...
Any way I can make that bottom right #eee i.o.w. main-right the same height (dynamic) as main-left - or have the .main background to apply...???
Thanks
Peter
PS Somebody with more credits should make a Susy tag in stackoverflow...
#main {
display: table;
background-color: #eee;
}
.main-left,
.main-right{
display: table-cell;
vertical-align: top;
}
.main-left {
background-color: #fff;
}
.main-right {
background-color: #eee;
}
This will make the two divs match each other as if they were adjacent table cells.
Don't worry, this doesn't qualify as using tables for layout, it's cool for columns, and it's not caused me any problems.
Of course, shitty old browsers don't support it, but you could use a .js script like ie9.js to patch it where necessary.

Resources