I’m trying to implement mixin customizing underline of text, like polyfill for CSS3 text-decoration properties: line, style, color, which are not supported yet by browsers.
My idea is to perform painting proper line in canvas, then convert it to data-uri and use it as background for target element. Problem is when compiling LESS with node.js, there is no canvas in environment. Technically I could use node-canvas to perform this task, but I don’t want to make any dependencies for node just to compile LESS.
Is there a good and simple alternative way to paint micro-image somehow and form data-uri based on this, not engaging external libraries or dependencies?
SOLVED: PNG data-generator code and some demos here. It’s .png
mixin that generates indexed-color png, accepts stream of bytes (string) as data, where 00 - transparent color, 01 - passed color.
I am not completely sure how exactly you want to implement the mixin (what all you want to do with the mixin), but maybe some of this can help.
First: You can use javascript interpolations in javascript implementations of LESS, using back-ticks.
Second: There are also some solutions available for drawing micro images in LESS ... I just recently came across this blog post: http://micheljansen.org/blog/entry/1238
And the idea here is to have a simple gif background and just change the color (using some embeded javascript to transform r g b to a 64 bit base). For example to do the wavy
line efect like the one used in css text-decoration-style:wavy;
you could use the following LESS code:
.wavyrgb(@r,@g,@b) {
@key: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
@b64: `function(r,g,b){var key=@{key};return key.charAt(((0&3)<<4)|(r>>4))+key.charAt(((r&15)<<2)|(g>>6))+key.charAt(g&63)+key.charAt(b>>2)+key.charAt(((b&3)<<4)|(255>>4))}(@{r},@{g},@{b})`;
background-image: ~"url(data:image/gif;base64,R0lGODlhBgADAIAAA@{b64}///yH5BAEAAAEALAAAAAAGAAMAAAIHTAB2lqlQAAA7)";
}
And then place the background image on the bottom for example:
.underwave {
text-decoration:none;
.wavyrgb(255,0,0); //red line
background-repeat:repeat-x;
background-position:bottom;
}
The output CSS:
.underwave {
text-decoration: none;
background-image: url(data:image/gif;base64,R0lGODlhBgADAIAAAP8AAP///yH5BAEAAAEALAAAAAAGAAMAAAIHTAB2lqlQAAA7);
background-repeat: repeat-x;
background-position: bottom;
}
The rest now are just some css hints to finalize the approach:
This way with positioning the background-image
to top or bottom, you get an overline or underline effect. Which are placed in the back of text using text-decoration-line
. If you want to place the line in front of the text, like in the option line-through
, you need to use the :afetr
pseudoclass in your CSS:
.throughwave {
text-decoration: none;
position:relative;
}
.throughwave:after {
background-image: url(data:image/gif;base64,R0lGODlhBgADAIAAAP8AAP///yH5BAEAAAEALAAAAAAGAAMAAAIHTAB2lqlQAAA7);
background-repeat: repeat-x;
background-position: center;
}
There have been also discussions on SO about adding a blinking effect ... for example with CSS animations here:
- How do you make an image blink?
- CSS3 animation: blinking overlay box
or you could do the blinking of an element using jQuery.
The combination of effects you can achieve with using multiple background images and position one on top, one on bottom for example.
Here I threw together a quick demo on jsfiddle.
Edit: Pure LESS mixin (no JS):
I wrote a new mixin to calculate the base64 color with LESS only, so
it works in all LESS implementations.
This is a LESS 1.4.0 solution:
.b64(@r,@g,@b) {
@test: "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" 0 1 2 3 4 5 6 7 8 9 "+" "/" "=";
@bit1: extract(@test, (floor(@r/16) + 1)); @bit2: extract(@test, (mod(@r,16)*4 + floor(@g/64) + 1)); @bit3: extract(@test, (mod(@g,64) + 1)); @bit4: extract(@test, (floor(@b/4) + 1)); @bit5: extract(@test, (mod(@b,4)*16 + 16));
b64-color: ~"@{bit1}@{bit2}@{bit3}@{bit4}@{bit5}";
}
This should work in all LESS versions >= 1.1.6:
.b64(@r,@g,@b) {
@1:"A"; @2:"B"; @3:"C"; @4:"D"; @5:"E"; @6:"F"; @7:"G"; @8:"H"; @9:"I"; @10:"J"; @11:"K"; @12:"L"; @13:"M"; @14:"N"; @15:"O"; @16:"P"; @17:"Q"; @18:"R"; @19:"S"; @20:"T"; @21:"U"; @22:"V"; @23:"W"; @24:"X"; @25:"Y"; @26:"Z"; @27:"a"; @28:"b"; @29:"c"; @30:"d"; @31:"e"; @32:"f"; @33:"g"; @34:"h"; @35:"i"; @36:"j"; @37:"k"; @38:"l"; @39:"m"; @40:"n"; @41:"o"; @42:"p"; @43:"q"; @44:"r"; @45:"s"; @46:"t"; @47:"u"; @48:"v"; @49:"w"; @50:"x"; @51:"y"; @52:"z"; @53:0; @54:1; @55:2; @56:3; @57:4; @58:5; @59:6; @60:7; @61:8; @62:9; @63:"+"; @64:"/"; @65:"=";
@modR16: @r - floor(@r/16)*16; @modG64: @g - floor(@g/64)*64; @modB4: @b - floor(@b/4)*4;
@pos1: (floor(@r/16) + 1); @pos2: (@modR16*4 + floor(@g/64) + 1); @pos3: (@modG64 + 1); @pos4: (floor(@b/4) + 1); @pos5: (@modB4*16 + 16);
@bit1: @@pos1; @bit2: @@pos2; @bit3: @@pos3; @bit4: @@pos4; @bit5: @@pos5;
b64-color: ~"@{bit1}@{bit2}@{bit3}@{bit4}@{bit5}";
}
The data-uri function is now built-in:
http://lesscss.org/functions/#misc-functions-data-uri