Compass sprite - avoid using extends when including a sprite - css

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

Related

Extending in a media query in Sass and Bootstrap 4

I am updating to the new Bootstrap version 4 which now uses Sass over Less, and my application that uses Bootstrap used the Less files directly rather than the fully compiled css distribution.
But now I've hit a snag - I understand that Sass doesn't allow you to use an #extend within a #media query, but what I don't understand is how I get around the simple problem of overloading a style on a larger screen.
For example, a stripped down version of my Sass looks like:
.box {
//mobile styles
background: green;
.logout-button {
//mobile styles for logout button
background: red;
}
}
//everything over 767px
#media (min-width: 768px) {
.box {
.logout-button {
#extend .btn-link; //bring in the Bootstrap button link style here
}
}
}
In this example, I want the .logout-button to use the .btn-link style from Bootstrap. But because you can't #extend like this, I'm totally confused as to how to achieve this.
Is there a completely different approach required in Sass compared to Less? Less allows you to do this so I'd be surprised if this was a limitation considering Bootstrap's recent switch.
Thanks in advance!
You are right, you can not #extend like this.
But you can #include some #mixin.
There is unfortunately no #mixin to create .btn-link variant by default in Bootstrap 4.
If you wanted some other variant, you could use these #mixins which are part of Bootstrap 4:
#include button-variant($background, $border, $active-background: darken($background, 7.5%), $active-border: darken($border, 10%))
or this
#include button-outline-variant($color, $color-hover: #fff)
(Useful list of Boostrap 4 mixins)
But if you need .btn-link you have to make your own #mixin. Something like this (it's copy/paste style of .btn-link in to new mixin):
//
// Link buttons
//
// Make a button look and behave like a link
#mixin btn-link() {
font-weight: $font-weight-normal;
color: $link-color;
background-color: transparent;
#include hover {
color: $link-hover-color;
text-decoration: $link-hover-decoration;
background-color: transparent;
border-color: transparent;
}
&:focus,
&.focus {
text-decoration: $link-hover-decoration;
border-color: transparent;
box-shadow: none;
}
&:disabled,
&.disabled {
color: $btn-link-disabled-color;
pointer-events: none;
}
// No need for an active state here
}
And then you can use it as you wish:
//everything over 767px
#media (min-width: 768px) {
.box {
.logout-button {
#include btn-link;
}
}
}
Nice article about this: SCSS - Extending Classes Within Media Queries

how to overwrite Susy settings at certain breakpoints

I’m using Susy’s gallery setting at a small breakpoint and (because of mobile first CSS structure), its getting passed to the larger breakpoint and I can’t figure out how to clear/overwrite it to allow my divs to span full width.
tablet output:
[div] [div] [div]
desired desktop output:
[ div ]
[ div ]
[ div ]
my attempt:
div {
#include gallery(4);
#media (min-width: 900px) {
#include break;
#include full;
}
}
see FIDDLE
I'm sure you already resolved this by now, but since I came up against the same issue I thought I'd post my solution.
Add the following mixin:
#mixin reset-gallery {
&:nth-child(1n) {
margin-left: 0;
margin-right: gutter();
}
&:last-child {
margin-right: 0;
}
}
and then reset your divs as follows:
#media (min-width: 900px) {
#include reset-gallery;
#include span(full);
}
Updated fiddle here. It might not work in all situations, but it worked for me and seems to work for your case also.

How to customize font size in Ionic Framework

I'm using ionic framework (with cordova) to develop mobile apps.
What I want to do is to increase the font size (in general in my app).
I've seen that in the official documentation : http://ionicframework.com/tutorials/customizing-ionic-with-sass/.
But I do not understand how to customize once sass is working.
I'm working in a tabs-based App like that : http://forum.ionicframework.com/uploads/default/269/9934610f0a08b8d2.png
I tried to manually add a class on the tab, but the result is not very clean... the text is cropped...
Is there an official way to change the font-size ?
I think you don't need to undersand everything on Sass.
In your project directory, in
.../yourProject/www/lib/ionic/scss
There is a file named _variables.scss where you will see something like this :
These are font-size variables, you just have to change these and then build the ionic css file.
I suggest you to use https://prepros.io/. I hope it helped you.
Figured I'd share what I've learnt in Ionic.
Basically, Ionic has a default set of sizes, colors, fonts for every single thing you can design and this set is stored in the _variables.scss file. This file is at lib/ionic/scss/_variables.scss
Open this file and search for what you want to alter. For example, I needed to increase the header font-size. So I searched in the _variables.scss file and found $bar-title-font-size.
It was defined as $bar-title-font-size: 17px !default;
Now, open your ionic.app.scss file and write something like
$bar-title-font-size: 25px !default;
***Remember to write the above statement before the #import "ionic/scss/ionic"; statement.
Save the file and your changes will instantly take effect. Ionic has made it that simple!!! :)
Search your project/www/css and edit style.css, and inside the file write:
{font-size:55px !important;}
change 55px to whatever size you need.
Often you want to decide when to use which icon size so I came up with the following solution.
CSS
/* Ionicon icons resizing css */
.ion-1x { font-size: 24px !important;}
.ion-2x { font-size: 48px !important;}
HTML
// in iconics framework
<ion-icon name="logo-pinterest" class="ion-1x"></ion-icon>
<ion-icon name="logo-twitter" class="ion-2x"></ion-icon>
// without ionics framework
<i class="ion-1x ion-social-pinterest"></i>
<i class="ion-2x ion-social-twitter"></i>
To make responsive font-size according to device for ionic2,
Add this in src/theme/variables.scss
// breakpoint mixin
#mixin breakpoint($mq01: 0, $mq2: false, $maxmin: max-width) {
#if $mq2 == false {
#media ($maxmin: $mq01) {
#content;
}
}
#else {
#media (min-width: $mq01) and (max-width: $mq2) {
#content;
}
}
}
// breakpoint variables
$lg: 1170px;
$md: 1024px;
$sm: 640px;
$xs: 480px;
// responsive font size mixin
#mixin font-size-map($font-size-map) {
#each $breakpoint, $font-size in $font-size-map {
#if $breakpoint == null {
font-size: $font-size;
} #else {
#include breakpoint($breakpoint) {
font-size: $font-size;
}
}
}
}
// font sizes
$html-font-size: (null: 16px, $md: 15px, $sm: 14px, $xs: 13px);
$paragraph-font-size: (null: 18px, $lg: 17px, $md: 16px, $sm: 15px, $xs: 14px);
include variable in local scss by adding: #include font-size-map($html-font-size);
// html
html {
#include font-size-map($html-font-size);
}
p {
#include font-size-map($paragraph-font-size);
}
Newer versions of Ionic (4 + 5) use CSS variables.
However, there is no variable for the font size. So, you can add a line like this to variables.css:
body ion-content {
font-size: 1.25rem;
}
Further reading
Global styling in Ionic apps
Setting a font family in an ionic app
I use Ionic for my apps and this is how I deal with resizing:
Find the class/element that you need to modify in CSS
Set padding:0 0 0 0; or to values you want (top,right,bottom,left).
Set font size
Set height
Set line-height
Edit: This is how I modified my tab items
.tab-item{
margin: 0;
line-height: 100px;
box-sizing: content-box;
font-size: 40px;
color:#FFFFFF;
font-family: 'Roboto-Light';
opacity: 1;
max-width: 200px;
}

How do Compass CSS Framework makes cleaner markup without presentational classes?

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!

Extending selectors from within media queries with Sass

I have an item class and a compact "modifier" class:
.item { ... }
.item.compact { /* styles to make .item smaller */ }
This is fine. However, I'd like to add a #media query that forces the .item class to be compact when the screen is small enough.
On first thought, this is what I tried to do:
.item { ... }
.item.compact { ... }
#media (max-width: 600px) {
.item { #extend .item.compact; }
}
But this generates the following error:
You may not #extend an outer selector from within #media. You may only
#extend selectors within the same directive.
How would I accomplish this using SASS without having to resort to copy/pasting styles?
The simple answer is: you can't because Sass can't (or won't) compose the selector for it. You can't be inside of a media query and extend something that's outside of a media query. It certainly would be nice if it would simply take a copy of it instead of trying to compose the selectors. But it doesn't so you can't.
Use a mixin
If you have a case where you're going to be reusing a block of code inside and outside of media queries and still want it to be able to extend it, then write both a mixin and an extend class:
#mixin foo {
// do stuff
}
%foo {
#include foo;
}
// usage
.foo {
#extend %foo;
}
#media (min-width: 30em) {
.bar {
#include foo;
}
}
Extend the selector within a media query from the outside
This won't really help your use case, but it is another option:
%foo {
#media (min-width: 20em) {
color: red;
}
}
#media (min-width: 30em) {
%bar {
background: yellow;
}
}
// usage
.foo {
#extend %foo;
}
.bar {
#extend %bar;
}
Wait until Sass lifts this restriction (or patch it yourself)
There are a number of ongoing discussions regarding this issue (please don't contribute to these threads unless you have something meaningful to add: the maintainers are already aware that users desire this functionality, it's just a question of how to implement it and what the syntax should be).
https://github.com/sass/sass/issues/1050
https://github.com/sass/sass/issues/456
For the record, here is how I ended up solving the problem with only duplicating generated styles once:
// This is where the actual compact styles live
#mixin compact-mixin { /* ... */ }
// Include the compact mixin for items that are always compact
.item.compact { #include compact-mixin; }
// Here's the tricky part, due to how SASS handles extending
.item { ... }
// The following needs to be declared AFTER .item, else it'll
// be overridden by .item's NORMAL styles.
#media (max-width: 600px) {
%compact { #include compact-mixin; }
// Afterwards we can extend and
// customize different item compact styles
.item {
#extend %compact;
/* Other styles that override %compact */
}
// As shown below, we can extend the compact styles as many
// times as we want without needing to re-extend
// the compact mixin, thus avoiding generating duplicate css
.item-alt {
#extend %compact;
}
}
I believe SASS/SCSS does not support the #extend directive inside of a media query. http://designshack.net/articles/css/sass-and-media-queries-what-you-can-and-cant-do/
You might need to use a mixin instead, though the code bloat needs to be weighed against your objective.
This is the cleanest, partial solution I've found. It takes advantage of #extend where possible and falls back to mixins when inside media queries.
Cross-Media Query #extend Directives in Sass
See the article for full details but the gist is that you call a mixin 'placeholder' that then decides whether to output #extend or an #include.
#include placeholder('clear') {
clear: both;
overflow: hidden;
}
.a {
#include _(clear);
}
.b {
#include _(clear);
}
.c {
#include breakpoint(medium) {
#include _(clear);
}
}
Ultimately it may not be better than just using mixins, which is currently the accepted answer.
I use breakpoints, but it's the same idea:
#mixin bp-small {
#media only screen and (max-width: 30em) {
#content;
}
How to use it:
.sidebar {
width: 60%;
float: left;
#include bp-small {
width: 100%;
float: none;
}
}
There is a text about mixins where you can find out more about this option.
Could you restructure?
.compact { //compact-styles }
.item {}
.item.compact { #extend .compact }
#media (max-width: 600px) {
.item { #extend .compact; }
}
If I understand the documentation correctly, that should work. I think the reason the way you're trying won't work is that it doesn't see .item.compact when it's parsing the #extend, but that's an uninformed guess, so take that with a truck load of salt! :)

Resources