A SASS/Compass sprite mixin with retina sprite-sheet option - sass

I'm trying to write a mixin using sass/Compass that will make use of available spriting functions for both regular-size images and their #2x/#3x counterparts. This is what I've done so far:
// including the three sprite maps
$icons : sprite-map("icons/*.png")
$icons2x : sprite-map("icons#2x/*.png")
$icons3x : sprite-map("icons#3x/*.png")
// the mixin
=retina-spritebox($name, $map: $icons, $rmap2x: $icons2x, $rmap3x: $icons3x, $display: block, $bg-color: transparent)
display: #{$display}
text-indent: -9999px
overflow: hidden
background: $bg-color $map sprite-position($map, $name)
+sprite-dimensions($map, $name)
#media only screen and (min--moz-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5), (min-resolution: 1.5dppx)
background: $rmap2x nth(sprite-position($rmap2x, $name), 1)/2 nth(sprite-position($rmap2x, $name), 2)/2
background-size: image-width(sprite-path($rmap2x))/2 image-height(sprite-path($rmap2x))/2
#media only screen and (min--moz-device-pixel-ratio: 2.5), only screen and (-o-min-device-pixel-ratio: 5/2), only screen and (-webkit-min-device-pixel-ratio: 2.5), only screen and (min-device-pixel-ratio: 2.5), (min-resolution: 2.5dppx)
background: $rmap3x nth(sprite-position($rmap3x, $name), 1)/3 nth(sprite-position($rmap3x, $name), 2)/3
background-size: image-width(sprite-path($rmap3x))/3 image-height(sprite-path($rmap3x))/3
Everything works exactly as intended – except the things happening inside those media queries. I'm trying to divide the width of the #2x sprite sheet and the x/y coordinates of its sprite by 2, but there doesn't seem to be any way to ensure that the width of the sprite sheet or the coordinates of the sprites will always be neatly divisible by 2.
I realise that I could just include the #2x image instead, but that would mitigate the performance gain of using a sprite sheet.
A solution would be greatly appreciated.

Try any of these two (if you are not using bower download the files from src/ folder)
https://github.com/Gaya/Retina-Sprites-for-Compass (separates the files in two different folders)
https://github.com/pixelmord/Retina-Sprites-for-Compass (saves 1 request)

Related

Trying to make the buttons clickable and canvas to draw on top of background image

I have this jsfiddle script that I am having trouble to do the following:
Respond to button click.
To show the box drawn on the canvas
I know that I could make this work if I add "z-index: -1" to
var sss = `
.container:before {
content: "";
position: absolute;
width: 200%;
height: 200%;
top: -50%;
left: -50%;
background: url("${url}") 50% 50% no-repeat;
-webkit-transition: all 1s;
-moz-transition: all 1s;
-ms-transition: all 1s
-o-transition: all 1s;
transition: all 1s;
}
`;
$(`<style id="dynastyle" type='text/css'>${sss}</style>`).appendTo("head");
But I don't want to do that for a peculiar reason that is too complicated to explain here.
Does anyone know how to get this to work? To be honest, I have no idea why the button is not clickable. enter link description here
Also, I need to be able to draw on top of the canvas. BTW, I don't want to draw the image in the canvas.
After tweaking it for a few hours, I finally got it working. Basically I needed to do the following:
enclosing the buttons in a div that has the position attribute and z-index'd (I used 1, I believe that the default value is 0, giving 1 to the buttons makes it bigger than the 0 for the background image).
place the canvas in a different div and use absolute position to overlay it on top of the div that has the background image and use z-index 1.
When all these two things are done, I can remove the z-index on the dynamic style for the background image. What has giving me a lot of trouble during this was that I keep forgetting to add the position attribute on the elements involved in the layering.

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

Auto hiding an image's left and right sides according to the browser width

So my image is 1920px x 150px
all I want is the image should remain at the center of the screen when the browser screen bocomes lessthan 1920px, it should auto hide an equal amount of pixels from left and right sides of the image.
eg., if the browser total width is 1520px, then 200px from left and 200px from right should be hidden (I don't want the image to be at the center allways)
Is there some way i can do this?
Thanks in advance
Instead of using the image in an <IMG> tag, use it as the background of a div, give it a class imgBG, and include these styles:
.imgBG{
background: url(images/imagename.jpg) no-repeat 50% top;
width: 100%;
height: 150px;
margin: auto;
}

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.

Transparent Background Image with a Gradient

Today I was designing a transparent PNG background that would only sit in the top left of a div, and the rest of the div would maintain a gradient background for all transparent areas of the PNG, and the rest of the div itself.
It might be better to explain through the code I thought might work:
#mydiv .isawesome {
/* Basic color for old browsers, and a small image that sits in the top left corner of the div */
background: #B1B8BD url('../images/sidebar_angle.png') 0 0 no-repeat;
/* The gradient I would like to have applied to the whole div, behind the PNG mentioned above */
background: -moz-linear-gradient(top, #ADB2B6 0%, #ABAEB3 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ADB2B6), color-stop(100%,#ABAEB3));
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ADB2B6', endColorstr='#ABAEB3',GradientType=0 );
}
What I've been finding is that most browsers pick one or the other - most choosing the gradient since its further down the CSS file.
I know some of the guys around here will say "just apply the gradient to the PNG you're making" - but thats not ideal because the div will maintain a dynamic height - sometimes being very short, sometimes being very tall. I know this gradient isn't essential but I thought it might be worth asking y'all what you thought.
Is it possible to have a background image, while keeping the rest of the background as a gradient?
Keep in mind that a CSS gradient is actually an image value, not a color value as some might expect. Therefore, it corresponds to background-image specifically, and not background-color, or the entire background shorthand.
Essentially, what you're really trying to do is layering two background images: a bitmap image over a gradient. To do this, you specify both of them in the same declaration, separating them using a comma. Specify the image first, followed by the gradient. If you specify a background color, that color will always be painted underneath the bottom-most image, which means a gradient will cover it just fine, and it will work even in the case of a fallback.
Because you're including vendor prefixes, you will need to do this once for every prefix, once for prefixless, and once for fallback (without the gradient). To avoid having to repeat the other values, use the longhand properties1 instead of the background shorthand:
#mydiv .isawesome {
background-color: #B1B8BD;
background-position: 0 0;
background-repeat: no-repeat;
/* Fallback */
background-image: url('../images/sidebar_angle.png');
/* CSS gradients */
background-image: url('../images/sidebar_angle.png'),
-moz-linear-gradient(top, #ADB2B6 0%, #ABAEB3 100%);
background-image: url('../images/sidebar_angle.png'),
-webkit-gradient(linear, left top, left bottom, color-stop(0%, #ADB2B6), color-stop(100%, #ABAEB3));
background-image: url('../images/sidebar_angle.png'),
linear-gradient(to bottom, #ADB2B6, #ABAEB3);
/* IE */
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ADB2B6', endColorstr='#ABAEB3', GradientType=0);
}
Unfortunately this doesn't work correctly in IE as it uses filter for the gradient, which it always paints over the background.
To work around IE's issue you can place the filter and the background image in separate elements. That would obviate the power of CSS3 multiple backgrounds, though, since you can just do layering for all browsers, but that's a trade-off you'll have to make. If you don't need to support versions of IE that don't implement standardized CSS gradients, you have nothing to worry about.
1 Technically, the background-position and background-repeat declarations apply to both layers here because the gaps are filled in by repeating the values instead of clamped, but since background-position is its initial value and background-repeat doesn't matter for a gradient covering the entire element, it doesn't matter too much. The details of how layered background declarations are handled can be found here.
You can use Transparency and gradients. Gradients support transparency. You can use this, for example, when stacking multiple backgrounds, to create fading effects on background images.
background: linear-gradient(to right, rgba(255,255,255,0) 20%,
rgba(255,255,255,1)), url(http://foo.com/image.jpg);
The order of the image and gradient is very KEY here, i want to make that clear. The gradient/image combo works best like this...
background: -webkit-gradient(linear, top, rgba(0,0,0,0.5), rgba(200,20,200,0.5)), url('../images/plus.png');
background-image will also work...
background-image: -webkit-gradient(linear, top, rgba(0,0,0,0.5), rgba(200,20,200,0.5)), url('../images/plus.png');
the gradient needs to come first... to go on top. The absolute key here though is that the gradient uses at least 1 RGBA color... the color(s) need to be transparent to let the image come through. (rgba(20,20,20,***0.5***)). putting the gradient first in you css places the gradient on top of the image, so the lower the alpha setting on you RGBAs the more you see the image.
Now on the other hand if you use the reverse order the PNG needs to have transparent properties, just like the gradient, to let the gradient shine through. The image goes on top so your PNG needs to be saved as a 24 bit in photoshop with alpha areas... or a 32 bit in fireworks with alpha areas (or a gif i guess... barf), so you can see the gradient underneath. In this case the gradient can use HEX RGB or RGBA.
The key difference here is the look. The image will be much more vibrant when on top. When underneath you have the ability to tune the RGBA values in the browser to get the desired effect... instead of editing and saving back and forth from your image editing software.
Hope this helps, excuse my over simplification.
This is possible using multiple background syntax:
.example3 {
background-image: url(../images/plus.png), -moz-linear-gradient(top, #cbe3ba, #a6cc8b);
background-image: url(../images/plus.png), -webkit-gradient(linear, left top, left bottom, from(#cbe3ba), to(#a6cc8b));
}
I read about this at Here's One Solution.
UPDATED
* {
margin: 0;
padding: 0;
}
html,
body {
width: 100%;
height: 100%;
}
.hero {
width: 100%;
height: 100%;
min-width: 100%;
min-height: 100%;
position: relative;
}
.hero::before {
background-image: url(https://images.unsplash.com/photo-1566640269407-436c75fc9495?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=750&q=80);
background-size: cover;
content: "";
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -2;
opacity: 0.4;
}
<div class="hero flex-center">
<div class="hero-message">
<h1 class="hero-title">Your text</h1>
<h1 class="hero-sub-title">Your text2</h1>
</div>
</div>
<div class="not-hero flex-center bg-info">
<div class="not-hero-message">
<h1 class="hero-title">Your text</h1>
</div>
</div>
** It's working**
Transparent images are not yet a CSS standard, yet they are supported by most modern browsers. However, this is part of the W3C CSS3 recommendation. Implementation varies from one client to another, so you will have to use more than one syntax for cross-browser compatibility.
http://www.handycss.com/effects/transparent-image-in-css/

Resources