Compass Sprite Image and Scale - sass

I've spent the past 4 hours trying to find a way to create a sprite image with Compass and sass that also automatically scales each individual image for use with the background-size property.
Nothing I've found works, can't believe it's that difficult.
Does any one have a working example?
Edit: This is what I have so far
#mixin resize-sprite($map, $sprite, $percent) {
$spritePath: sprite-path($map);
$spriteWidth: image-width($spritePath);
$spriteHeight: image-height($spritePath);
$width: image-width(sprite-file($map, $sprite));
$height: image-height(sprite-file($map, $sprite));
#include background-size(ceil($spriteWidth * ($percent/100)) ceil($spriteHeight * ($percent/100)));
width: ceil($width*($percent/100));
height: ceil($height*($percent/100));
background-position: 0 floor(nth(sprite-position($map, $sprite), 2) * ($percent/100) );
}
#mixin resize-sprite-set($map, $percent, $only...) {
$name: sprite_map_name($map);
#each $sprite in sprite_names($map) {
#if length($only) == 0 or index($only, $sprite) != false {
.#{$name}-#{$sprite} {
#include resize-sprite($map, $sprite, $percent);
}
}
}
}
The mixin returns no errors.
$my-icons-spacing: 10px; // give some space to avoid little pixel size issues on resize
#import "my-icons/*.png";
$my-icons-sprite-dimensions: true;
#include all-my-icons-sprites;
// the fun part
.small-icons { // overriding all sprites
#include resize-sprite-set($my-icons-sprites, 40); // 40% sized
}
.some-part-of-my-site {
#include resize-sprite-set($my-icons-sprites, 40, logo, ok); // will create overrides only for sprites "logo" and "ok"
}
I get the following error message from the above implementation when I try to compile. Via Prepros App.
remove ../images/my-icons-s9e77ab1ef1.png
create ../images/my-icons-s9e77ab1ef1.png
error style.scss (Line 62 of _mixins.scss: Undefined mixin 'resize-sprite-set'.)
identical ../css/style.css

I've also done some research on this. This gist is what I came up with:
https://gist.github.com/apauly/7917906
Update:
The solution depends on three key-parts:
scale width
scale height
get background-position
0.
Grab the dimensions for both, the complete sprite and the single icon:
$icon-file: sprite-file($map, $icon);
$icon-width: image-width($icon-file);
$icon-height: image-height($icon-file);
$sprite-file: sprite-path($map);
$sprite-width: image-width($sprite-file);
$sprite-height: image-height($sprite-file);
1.
Consider a div displaying a sprite as its background. Set background-size: 100%; to make sure, that the background sprite covers the full width of the div.
If one would use width: 100%;, the result would be something like this:
+----------------+
|--| |
|----------------|
|--------| | <--- This is the sprite image we want to display
|------| |
+----------------+
So we need to enlarge our background to get something like this: (the div should have overflow:hidden though)
+----------------+
|---------| |
|-----------------------|
|----------------| | <---
|-------------| |
+----------------+
To achieve that, just divide the width of the complete sprite by the width of the single icon:
width:percentage($sprite-width / $icon-width);
2.
This one is basically inspired by a blog post form tkenny:
http://inspectelement.com/tutorials/a-responsive-css-background-image-technique/
The resulting sass code is this:
display: block;
height: 0;
padding-bottom: percentage($icon-height / $icon-width);
background-size: 100%;
3.
The rest is just some basic math to calculate the top spacing of the icon inside of the sprite as a relative value:
Get the space from the top in pixels (a negative value):
$space-top:floor(nth(sprite-position($map, $icon), 2));
Sass will need a px-value
#if $space-top == 0 {
$space-top: 0px
}
Set the background position with percentages:
background-position:0 percentage(
-1 * $space-top / ( $sprite-height - $icon-height )
);

Here's a mixin for resizing sprites that works beautifully
#mixin resize-sprite($map, $sprite, $percent) {
$spritePath: sprite-path($map);
$spriteWidth: image-width($spritePath);
$spriteHeight: image-height($spritePath);
$width: image-width(sprite-file($map, $sprite));
$height: image-height(sprite-file($map, $sprite));
#include background-size(ceil($spriteWidth * ($percent/100)) ceil($spriteHeight * ($percent/100)));
width: ceil($width*($percent/100));
height: ceil($height*($percent/100));
background-position: 0 floor(nth(sprite-position($map, $sprite), 2) * ($percent/100) );
}
and the github it came from:
https://gist.github.com/darren131/3410875

Related

How does the flag at?

There is a grid span(12)
There are two blocks of text
.main-container
.content text text text text text text text text text
.sidebar text text text text text text text text text
Want to do so
Write the code
span(6 at 1) //
span(3 as 9) //
But don't get desired. Here's the whole code.
$debug: (image: show, color: rgba(#66f, .25), output: background, toggle: top right)
$susy: (columns: 12, gutters: 1/4, math: fluid, gutter-position: inside, debug: $debug)
.main-container
#include container(80%)
.content
width: 100%
height: 100%
#include span(6 at 1)
.sidebar
width: 100%
height: 100%
#include span(3 at 9)
I thought that the flag at designed exactly for this purpose. But experiment has shown that I'm wrong. On this question - how to work with the flag at? ow to achieve the desired result using the at?
The at flag is only used in this way for isolation output ('output': 'isolate'). That's because floats are relative, and Susy doesn't know their original position unless you isolate them. Isolation is useful in some cases, but it's better to use push and pull to move floated elements into relative positions when needed. Something like this:
.content {
height: 100%;
#include span(6);
#inlcude push(1);
}
.sidebar {
height: 100%;
#include span(3);
#include push(1);
}
If you do use isolation, it would be something like this:
.content {
height: 100%;
#include span(isolate 6 at 2); // position is 1-indexed
}
.sidebar {
height: 100%;
#include span(isolate 3 at 9);
}
I removed width: 100% because span overrides width anyway.

Using sprite for retina with SASS/Compass

I'm working with SASS/Compass sprite libraray and I'm trying to configure my sprite to work with 3 icon sizes: 1x, 1.5x and 2x (retina)
this is the import of the folders:
#import "icons10/*.png";
#include all-icons10-sprites;
#import "icons15/*.png";
#include all-icons15-sprites;
#import "icons20/*.png";
#include all-icons20-sprites;
this is a mixin I am writing to manage these sprites:
#mixin my-icon($name) {
#extend .icons10-#{$name};
#media (-webkit-min-device-pixel-ratio: 1.5) {
#extend .icons15-#{$name};
background-position: 100% 100%;
}
#media (-webkit-min-device-pixel-ratio: 2) {
#extend .icons20-#{$name};
}
$icon-width: icons10-sprite-width($name);
$icon-height: icons10-sprite-height($name);
width: $icon-width;
height: $icon-height;
}
I'm completely clueless on how to manage backround-size and background-position in order to make the 1.5x and the 2x library to work. My questions are:
is there a retina solution for this specific SASS library?
I can manage my manual solution if I can fetch the sprite's dimensions themselves, but I don't understand how can I fetch the dimensions of the whole sprite
There is no such build in solution in SASS so far. But if you are willing to switch to sprite maps, there is a way to get the sprite maps size:
background-size: image-width(sprite-path( [your sprit emap] )) image-height(sprite-path( [your sprite map] ))
There is a great piece of code from Gaya Kessler on retina sprites for compass you should check out: Retina Sprites for Compass.
Adding your third icon size shouldn't be a problem.
try this:
https://gist.github.com/alanhogan/2878758
if sprite-url not work, you can try sprite-file

Making all photos square via css

I'm trying to make a series of photos into square photos. They may be rectangular horizontally (i.e. 600x400) or vertically (400x600), but I want to get them to be 175x175 either way. My thought was to max-height or max-width the smaller side, and not allow overflow beyond 175px on the larger side...however, I'm having problems with it.
Is this possible with css?
Below is my attempt, but it giving rectangles still:
<div style="min-height:175px; overflow:hidden; max-height:175px;">
<img style="min-width:175px; overflow:hidden; max-height:175px;" src="/photo.png">
</div>
You can set the width/height of the parent div then set the child img tag to width:100%; height: auto;
That will scale the image down to try to fit the parent with aspect ratio in mind.
You can also set the image as a background-image on the div
Then if you can use css3 you can mess with the background-size property.
It's attributes are: contain, cover, or a specificed height (50%, 50%) (175px, 175px)
You could also try to center the picture with background-position
<div style="background-image:url(some.png); background-size: cover; background-position: 50%">
Here's an up to date and simple answer.
For instance, if you want a squared image inside of a container.
Let's say you want the image to take 100% of the container height and have a dynamic width equal to the height:
.container {
height: 500px; /* any fixed value for the parent */
}
.img {
width: auto;
height: 100%;
aspect-ratio: 1; /* will make width equal to height (500px container) */
object-fit: cover; /* use the one you need */
}
You can switch width and height values (container & image) if you want to base the 100% on the container's width and have a computed height equal to the width.
You can use object-fit, which is widely supported in all major browsers. When set to cover, the browser will crop the image when you set the width and height properties, rather the stretching it.
<img src="whatever.jpg">
img {
width: 175px;
height: 175px;
object-fit: cover;
}
Okay I got this.
Don't know if it's too late or what, but I've come up with a 100% pure CSS way of creating square thumbnails. It's something that I've been trying to find a solution for for quite a while and have had no luck. With some experimentation, I've got it working. The main two attributes to use are OVERFLOW:HIDDEN and WIDTH/HEIGHT:AUTO.
Okay here's what to do:
Let's say you have a batch of images of varying shapes and sizes, some landscape, some portrait, but all, of course, rectangular. The first thing to do is categorize the image links (thumbnails) by either portrait or landscape, using a class selector. Okay, so let's say you want just to create two thumbnails, to make this simpler. you have:
img1.jpg (portrait) and
img2.jpg (landscape)
For HTML it would look like this:
<a class="portrait" href="yoursite/yourimages/img1.jpg"><img src="yoursite/yourimages/img1.jpg /></a>
<a class="landscape" href="yoursite/yourimages/img2.jpg"><img src="yoursite/yourimages/img2.jpg /></a>
So, at this point since there is no css yet, the above code would give you your full-sized image as a thumbnail which would link to the same full-sized image. Right, so here's the css for both portrait and landscape. There are two declarations for each (the link and the link's image):
.landscape {
float:left;
width:175px;
height:175px;
overflow:hidden;
}
.landscape img{
width:auto;
height: 175px;
}
.portrait {
float:left;
width:175px;
height:175px;
overflow:hidden;
}
.portrait img {
width:175px; <-- notice these
height: auto; <-- have switched
}
The most important things are the width and height and the overflow:hidden. Float left isn't necessary for this to work.
In the landscape thumbnail declaration (.landscape) the bounding box is set to 175 x 175 and the overflow is set to hidden. That means that any visual information larger than that containing 175px square will be hidden from view.
For the landscape image declaration (.landscape img), the height is fixed at 175px, which resizes the original height and the width is set to auto, which resizes the original width, but only to the point of relating to the bounding square, which in this case is 175px. So rather than smush the width down into the square, it simply fills the square and then any extra visual information in the width (i.e. the overflow) is hidden with the overflow:hidden.
It works the same way for portrait, only that the width and height is switched, where height is auto and width is 175px. Basically in each case, whatever dimension exceeds the other is set to auto, because naturally the larger dimension would be the one that would overflow outside of the set thumbnail dimensions (175px x 175x).
And if you want to add margins between thumbs, for instance a 5px white margin, you can use the border property, otherwise there will be no margin where the information is overflowing.
Hope this makes sense.
Determine width and height of image, then active portrait or landscape class of the image. If portrait do {height:175px; width:auto}. If landscape, reverse height and width.
I highly suggestion the NailThumb jquery plugin for anyone that is looking to do this. It allows you to create square thumbnails without distortion. http://www.garralab.com/nailthumb.php
This might help.
CSS:
.image{
-moz-border-radius: 30px; /* FF1+ */
-webkit-border-radius: 30px; /* Saf3-4 */
border-radius: 30px; /* Opera 10.5, IE 9, Saf5, Chrome */
}
HTML:
<div class="image"></div>
This worked for me. Just put the URL to the image inside the div.

Compass sprite position-x

I'm using the compass sprite helpers to position an icon and it works on the y axis, but it's positioned at 0 on the x axis. Now I could set the x offset to a fixed value, but I'd rather have it set to "right".
This is my code now:
background: {
url: sprite-url($icons-sprite);
repeat: no-repeat;
position: sprite-position($icons-sprite, nav-active);
}
This is what I'm trying to achieve (pseudo-code):
background: {
url: sprite-url($icons-sprite);
repeat: no-repeat;
position: right sprite-position-y($icons-sprite, nav-active);
}
Does anyone have a solution for this?
Automatic sprites
Before creating the sprite map, you must specify the sprite engine you want to have the sprite on the right side of the sprite map (see the documentation for further information):
$icons-nav-active-position: 100%;
#import "icons/*.png";
Then call the function sprite-position() as the usual:
position: sprite-position($icons-sprite, nav-active);
Manual sprites
When you call sprite-map(), you must pass the argument $<map>-<sprite>-position: 100% (where <map> represents the folder name that contains your sprites):
$icons-sprite: sprite-map("icons/*.png", $icons-nav-active-position: 100%);
background: {
url: sprite-url($icons-sprite);
repeat: no-repeat;
position: sprite-position($icons-sprite, nav-active);
}
Note 1: you can pass the argument $position: 100% to set the position for all the sprites.
Note 2: before Compass 0.12.1, the arguments to pass to sprite-map() does not start with <map>-. See the issue 828.

Sass calculate percent minus px

I want to be able to do the following:
height: 25% - 5px;
Obviously when I do that I get the error:
Incompatible units: 'px' and '%'.
Sass cannot perform arithmetic on values that cannot be converted from one unit to the next. Sass has no way of knowing exactly how wide "100%" is in terms of pixels or any other unit. That's something only the browser knows.
You need to use calc() instead. Check browser compatibility on Can I use...
.foo {
height: calc(25% - 5px);
}
If your values are in variables, you may need to use interpolation turn them into strings (otherwise Sass just tries to perform arithmetic):
$a: 25%;
$b: 5px;
.foo {
width: calc(#{$a} - #{$b});
}
There is a calc function in both SCSS [compile-time] and CSS [run-time]. You're likely invoking the former instead of the latter.
For obvious reasons mixing units won't work compile-time, but will at run-time.
You can force the latter by using unquote, a SCSS function.
.selector { height: unquote("-webkit-calc(100% - 40px)"); }
$var:25%;
$foo:5px;
.selector {
height:unquote("calc( #{$var} - #{$foo} )");
}
IF you know the width of the container, you could do like this:
#container
width: #{200}px
#element
width: #{(0.25 * 200) - 5}px
I'm aware that in many cases #container could have a relative width. Then this wouldn't work.
Sorry for reviving old thread - Compass' stretch with an :after pseudo-selector might suit your purpose - eg. if you want a div to fill width from left to (50% + 10px) of screen you could use (in SASS indented syntax):
.example
background: red
+stretch(0, -10px, 0, 0)
&:after
+stretch(0, 0, 0, 50%)
content: ' '
background: blue
The :after element fills 50% to the right of .example (leaving 50% available for .example's width), then .example is stretched to that width plus 10px.
Just add the percentage value into a variable and use #{$variable}
for example
$twentyFivePercent:25%;
.selector {
height: calc(#{$twentyFivePercent} - 5px);
}

Resources