Categories
Original Tips

Invert a whole webpage with CSS only

Reading Time: 2 minutes

I recently saw Paul Irish’s jQuery invert page plugin. It inverts every color on a webpage including images or CSS. This reminded me of the invert color keyword that’s allowed on outlines (and sadly only supported by Opera and IE9+). So I wondered how it could be exploited to achieve the same effect through CSS alone. Turned out to be quite simple actually:

body:before { 
	content:"";
	position:fixed;
	top:50%; left: 50%;
	z-index:9999;
	width:1px; height: 1px;
	outline:2999px solid invert;
}

Not even pointer-events:none; is needed, since outlines don’t receive pointer events anyway, and there’s no issue with scrollbars since they don’t contribute to scrolling. So this is not even CSS3, it’s just plain ol’ CSS 2.1.

And here’s a bookmarklet to inject it into any given page: Invert page

Note:This will only work on Opera and IE9+ since they’re currently the only ones supporting the color keyword ‘invert’ on outlines. However, it’s probably possible to add Firefox support too with SVG filters, since they support them on HTML elements as well.

As for why would someone want to invert a page… I guess it could be useful for people that can read white text on dark backgrounds more easily, April fools jokes, konami code fun and stuff like that.

Update: Mozilla is planning to never support invert because there’s a loophole in the CSS 2.1 spec that allows them to do that. However, you can push them to support it by voting on the relevant issue.

Categories
Original Tips

Create complex RegExps more easily

Reading Time: 2 minutes

When I was writing my linear-gradient() to -webkit-gradient() converter, I knew in advance that I would have to use a quite large regular expression to validate and parse the input. Such a regex would be incredibly hard to read and fix potential issues, so I tried to find a way to cut the process down in reusable parts.

Turns out JavaScript regular expression objects have a .source property that can be used in the RegExp constructor to create a new RegExp out of another one. So I wrote a new function that takes a string with identifiers for regexp replacements in {{ and }} and replaces them with the corresponding sub-regexps, taken from an object literal as a second argument:

/**
 * Create complex regexps in an easy to read way
 * @param str {String} Final regex with {{id}} for replacements
 * @param replacements {Object} Object with the replacements
 * @param flags {String} Just like the flags argument in the RegExp constructor
 */
RegExp.create = function(str, replacements, flags) {
	for(var id in replacements) {
		var replacement = replacements[id],
			idRegExp = RegExp('{{' + id + '}}', 'gi');

		if(replacement.source) {
			replacement = replacement.source.replace(/^\^|\$$/g, '');
		}

		// Don't add extra parentheses if they already exist
		str = str.replace(RegExp('\\(' + idRegExp.source + '\\)', 'gi'), '(' + replacement + ')');

		str = str.replace(idRegExp, '(?:' + replacement + ')');
	}

	return RegExp(str, flags);
};

If you don’t like adding a function to the RegExp object, you can name it however you want. Here’s how I used it for my linear-gradient() parser:

self.regex = {};

self.regex.number = /^-?[0-9]*\.?[0-9]+$/;
self.regex.keyword = /^(?:top\s+|bottom\s+)?(?:right|left)|(?:right\s+|left\s+)?(?:top|bottom)$/;

self.regex.direction = RegExp.create('^(?:{{keyword}}|{{number}}deg|0)$', {
	keyword: self.regex.keyword,
	number: self.regex.number 
});

self.regex.color = RegExp.create('(?:{{keyword}}|{{func}}|{{hex}})', {
	keyword: /^(?:red|tan|grey|gray|lime|navy|blue|teal|aqua|cyan|gold|peru|pink|plum|snow|[a-z]{5,20})$/,
	func: RegExp.create('^(?:rgb|hsl)a?\\((?:\\s*{{number}}%?\\s*,?\\s*){3,4}\\)$', {
		number: self.regex.number
	}),
	hex: /^#(?:[0-9a-f]{1,2}){3}$/
});

self.regex.percentage = RegExp.create('^(?:{{number}}%|0)$', {
	number: self.regex.number
});

self.regex.length = RegExp.create('{{number}}{{unit}}|0', {
	number: self.regex.number,
	unit: /%|px|mm|cm|in|em|rem|en|ex|ch|vm|vw|vh/
});

self.regex.colorStop = RegExp.create('{{color}}\\s*{{length}}?', {
	color: self.regex.color,
	length: self.regex.length
}, 'g');

self.regex.linearGradient = RegExp.create('^linear-gradient\\(\\s*(?:({{direction}})\\s*,)?\\s*({{colorstop}}\\s*(?:,\\s*{{colorstop}}\\s*)+)\\)$', {
	direction: self.regex.direction,
	colorStop: self.regex.colorStop
}, 'i');

(self in this case was a local variable, not the window object)

Categories
Original

Convert standard gradient syntax to -webkit-gradient and others

Reading Time: < 1 minute

Screenshot of the demoI hate -webkit-gradient() with a passion. Its syntax is cumbersome and it’s really limited: No angle support, no <length>s in color stop positions, no implied color stop positions, no elliptical gradients… So, I was really happy, when Webkit implemented the standard syntax this January. However, we’re still stuck with the horrid -webkit-gradient() for quite a while, since older Webkit browsers that don’t support it are widely used at this time.

Today, I decided to finally spare myself the hassle of converting my standard gradient syntax to -webkit-gradient() by hand. Tasks like that shouldn’t be handled by a human. So, I coded a little script to do the chore. Hope it helps you too:
View demo

It currently only supports linear gradients, but I plan to add radial ones in the future. Also, when I get around to cleaning up the code a bit, I’ll add it on Github.

(Hope I didn’t leave in any very stupid bug, it’s really late here and I’m half asleep.)

Categories
Original Tips

Beveled corners & negative border-radius with CSS3 gradients

Reading Time: < 1 minute

Just found out how to do beveled corners and simulate negative border radius without images, by utilizing CSS gradients once again. It’s amazing how many CSS problems can be solved with gradients alone. Read the text in the dabblet below to find out how (or just check the code):

It also falls back to a solid color background if CSS gradients are not supported. It will work on Firefox 3.6+, Chrome, Safari, Opera 11.10+ and IE10+.

PS: For my twitter friends, I had already written this when the robbers came and I was about to post it. I might have been really calm, but not as much as making CSS experiments the same day I was robbed and threatened by a gun 😛

Categories
Original Tips

Custom <select> drop downs with CSS3

Reading Time: 2 minutes

The CSS3 Basic UI module defines pointer-events as:

The pointer-events property allows authors to control whether or when an element may be the target of user pointing device (pointer, e.g. mouse) events. This property is used to specify under which circumstance (if any) a pointer event should go “through” an element and target whatever is “underneath” that element instead. This also applies to other “hit testing” behaviors such as dynamic pseudo-classes (:hover, :active, :focus), hyperlinks, and Document.elementFromPoint().

The property was originally SVG-only, but eventually browsers and the W3C adopted a more limited version for HTML elements too.

It can be used in many use cases that weren’t possible before (or the solution was overly complicated), one of them being to create custom-looking <select> drop downs, by overlaying an element over the native drop down arrow (to create the custom one) and disallowing pointer events on it. Here’s a quick example:

-webkit-appearance: none was needed in Webkit to turn off the native OSX appearance (in OSX and maybe Safari on Windows, I didn’t test that). However, since that also removes the native drop down arrow, our custom arrow now obscures part of the text, so we had to add a 30px padding-right to the select element, only in Webkit.

Categories
Original Tips

Checkerboard pattern with CSS3

Reading Time: < 1 minute

A while ago, I wrote a post on creating simple patterns with CSS3 gradients. A common pattern I was unable to create was that of a regular, non-rotated checkerboard. However, I noticed today that by giving a different background-position to every triangle in the pattern tile, a checkerboard can be easily created:

View in Gecko or Webkit.
Webkit seems to have an odd rendering bug, so it needed a background-size override and it still doesn’t look perfect. Oh well, reported the bug and moved on.

Categories
Original Releases

Incrementable length values in text fields

Reading Time: < 1 minute

I always loved that Firebug and Dragonfly feature that allows you to increment or decrement a <length> value by pressing the up and down keyboard arrows when the caret is over it. I wished my Front Trends slides supported it in the editable examples, it would make presenting so much easier. So, I decided to implement the functionality, to use it in my next talk.

If you still have no idea what I’m talking about, you can see a demo here:
View demo

You may configure it so that it only does that when modifiers (alt, ctrl and/or shift) are used by providing a second argument to the constructor and/or change the units supported by filling in the third argument. However, bear in mind that holding down the Shift key will make it increment by ±10 instead of ±1 and that’s not configurable (it would add too much unneeded complexity, I’m not even sure whether it’s a good idea to make the other thing configurable either).

You may download it or fork it from it’s Github repo.

And if you feel creative, you may improve it by fixing an Opera bug I gave up on: When the down arrow is pressed, the caret moves to the end of the string, despite the code telling it not to.

Categories
Original Tips

Convert PHP serialized data to Unicode

Reading Time: 2 minutes

I recently had to convert a database of a large greek website from single-byte greek to Unicode (UTF-8). One of the problems I faced was the stored PHP serialized data: As PHP stores the length of the data (in bytes) inside the serialized string, the stored serialized strings could not be unserialized after the conversion.

I didn’t want anyone to go through the frustration I went through while searching for a solution, so here is a little function I wrote to recount the string lengths, since I couldn’t find anything on this:

function recount_serialized_bytes($text) {
	mb_internal_encoding("UTF-8");
	mb_regex_encoding("UTF-8");

	mb_ereg_search_init($text, 's:[0-9]+:"');

	$offset = 0;

	while(preg_match('/s:([0-9]+):"/u', $text, $matches, PREG_OFFSET_CAPTURE, $offset) ||
		  preg_match('/s:([0-9]+):"/u', $text, $matches, PREG_OFFSET_CAPTURE, ++$offset)) {
		$number = $matches[1][0];
		$pos = $matches[1][1];

		$digits = strlen("$number");
		$pos_chars = mb_strlen(substr($text, 0, $pos)) + 2 + $digits;

		$str = mb_substr($text, $pos_chars, $number);

		$new_number = strlen($str);
		$new_digits = strlen($new_number);

		if($number != $new_number) {
			// Change stored number
			$text = substr_replace($text, $new_number, $pos, $digits);
			$pos += $new_digits - $digits;
		}

		$offset = $pos + 2 + $new_number;
	}

	return $text;
}

My initial approach was to do it with regular expressions, but the PHP serialized data format is not a regular language and cannot be properly parsed with regular expressions. All approaches fail on edge cases, and I had lots of edge cases in my data (I even had nested serialized strings!).

Note that this will only work when converting from single-byte encoded data, since it assumes the stored lengths are the string lengths in characters. Admittedly, it’s not my best code, it could be optimized in many ways. It was something I had to write quickly and was only going to be used by me in a one-time conversion process. However, it works smoothly and has been tested with lots of different serialized data. I know that not many people will find it useful, but it’s going to be a lifesaver for the few ones that need it.

Categories
Original Tips

Checkerboard, striped & other background patterns with CSS3 gradients

Reading Time: 2 minutes

Screenshot of the CSS3 patterns I came up withYou’re probably familiar with CSS3 gradients by now, including the closer to the standard Mozilla syntax and the ugly verbose Webkit one. I assume you know how to add multiple color stops, make your gradients angled or create radial gradients. What you might not be aware of, is that CSS3 gradients can be used to create many kinds of commonly needed patterns, including checkered patterns, stripes and more.

View demo (Works in Webkit, Firefox 3.6+, Opera 11.50+ and IE10+)

The main idea behind the technique is the following, taken from the CSS3 Images spec:

If multiple color-stops have the same position, they produce an infinitesimal transition from the one specified first in the rule to the one specified last. In effect, the color suddenly changes at that position rather than smoothly transitioning.

I guess this makes it obvious how to create the tile for the stripes (unless you’ve never created a striped background before, but teaching you this is beyond the scope of this post). For example the gradient for the horizontal stripes is:

background-color: #0ae;
background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(.5, rgba(255, 255, 255, .2)), color-stop(.5, transparent), to(transparent));
background-image: -moz-linear-gradient(rgba(255, 255, 255, .2) 50%, transparent 50%, transparent);
background-image: -o-linear-gradient(rgba(255, 255, 255, .2) 50%, transparent 50%, transparent);
background-image: linear-gradient(rgba(255, 255, 255, .2) 50%, transparent 50%, transparent);

Why transparent instead of the actual colors we want? For flexibility. background-color serves two purposes here: Setting the color of half the stripes and serving as a fallback for browsers that don’t support gradients.

However, without anything else, the tile will occupy the whole container. To control the size of each tile, you can use background-size:

-webkit-background-size: 50px 50px;
-moz-background-size: 50px 50px;
background-size: 50px 50px;

To create the picnic-style pattern, you just overlay horizontal stripes on vertical stripes.

The hardest one to figure out was the checkered pattern. It consists of two 45° linear gradients and two -45° linear gradients, each containing ¼ of the dark squares. I still haven’t managed to think of a way to create a regular checkerboard (not at 45°) without needing an unacceptably large number of gradients. It will be very easily possible if conical gradients start being supported (currently they’re not even in the spec yet).

Can you think of any other popular patterns that can be created with CSS3 and no images? If so, let me know with a comment. Cheers! 🙂

Added afterwards: Other patterns

There are far more pattern designs possible with CSS3 gradients than I originally thought. For more details, see this later post.

Categories
News Original

rgba.php v1.2: Improved URL syntax, now at Github

Reading Time: < 1 minute

I wrote the first version of rgba.php as a complement to an article on RGBA that I posted on Februrary 2009.
Many people seemed to like the idea and started using it. With their valuable input, I made many changes and released v.1.1 (1.1.1 shortly after I posted the article due to another little fix) on October 2009.
More than a year after, quite a lot of people still ask me about it and use it, so I decided to make a github repo for it and release a new version, with a much easier to use syntax for the URL, which lets you just copy and paste the color instead of rewriting it:

background: url('rgba.php/rgba(255, 255, 255, 0.3)');
background: rgba(255, 255, 255, 0.3);

instead of:

background: url('rgba.php?r=255&g=255&b=255&a=30');
background: rgba(255, 255, 255, 0.3);

I also made a quick about/demo page for it.
Enjoy 🙂