Blog

38 posts 2009 16 posts 2010 50 posts 2011 28 posts 2012 15 posts 2013 7 posts 2014 10 posts 2015 5 posts 2016 4 posts 2017 7 posts 2018 2 posts 2019 17 posts 2020 7 posts 2021 7 posts 2022 11 posts 2023 7 posts 2024 4 posts 2025

StronglyTyped: A library for strongly typed properties & constants in JavaScript

2 min read 0 comments Report broken page

StronglyTypedI’ll start by saying I love the loosely typed nature of JavaScript. When I had to work with strongly typed languages like Java, it always seemed like an unnecessary hassle. On the contrary, my boyfriend even though very proficient with HTML, CSS and SVG, comes from a strong Java background and hates loosely typed scripting languages. So, to tempt him into JS and keep him away from heavy abstractions like Objective-J, I wrote a little library that allows you to specify strongly typed properties (and since global variables are also properties of the window object, those as well) of various types (real JS types like Boolean, Number, String etc or even made up ones like Integer) and constants (final properties in Java). It uses ES5 getters and setters to do that and falls back to regular, loosely typed properties in non-supporting browsers.

Also, as a bonus, you get cross-browser Function.prototype.bind and Array.prototype.forEach and a robust type checking function: StronglyTyped.is(type, value).

Example: Strongly typed properties

You define strongly typed properties by using the corresponding methods of the StronglyTyped object. For example, the following snippet defines a boolean property called “foo” on an object literal:

var o = {};

StronglyTyped.boolean(o, ‘foo’, true);

console.log(o.foo); // prints true

o.foo = false; console.log(o.foo); // prints false

o.foo = ‘bar’; // TypeError: foo must be of type Boolean. bar is not.

Example: Constants

You define constants by using the constant method of the StronglyTyped object. For example, the following snippet defines a global MAGIC_NUMBER constant:

var o = {};

StronglyTyped.constant(window, ‘MAGIC_NUMBER’, 3.1415926535);

console.log(MAGIC_NUMBER); // prints 3.1415926535

MAGIC_NUMBER = 4; console.log(MAGIC_NUMBER); // prints 3.1415926535

Please note that constants only become read-only after they first get a non-undefined value. For example:

StronglyTyped.constant(window, ‘MAGIC_NUMBER’);

console.log(MAGIC_NUMBER); // prints undefined

MAGIC_NUMBER = undefined;

console.log(MAGIC_NUMBER); // prints undefined

MAGIC_NUMBER = 3.1415926535; console.log(MAGIC_NUMBER); // prints 3.1415926535

MAGIC_NUMBER = 4; console.log(MAGIC_NUMBER); // prints 3.1415926535

Supported types

The property types currently supported by StronglyTyped are:

  • Array
  • Boolean
  • Date
  • Function
  • Integer
  • Number
  • RegExp
  • String

null and undefined are valid in every type. NaN and Infinity values are accepted in both the Number and the Integer types.

If you want to use a type that’s not among the above but either is native to the browser (for example Element) or a global object, you can use the generic method StronglyTyped.property(type, object, property [, initialValue]):

var o = {};

StronglyTyped.property(‘Element’, o, ‘foo’, document.body);

console.log(o.foo); // prints a representation of the <body> element

o.foo = document.head; console.log(o.foo); // prints a representation of the <head> element

o.foo = 5; // TypeError: foo must be of type Element. 5 is not.

Browser support

It should work on every browser that supports Object.defineProperty or __defineGetter__ and __defineSetter__. As you can see from kangax’s awesome compatibility tables for Object.defineProperty and __define(G|S)etter__, those are:

  • Firefox 3.5+
  • IE8 (only on DOM elements)
  • IE9+
  • Opera 10.5+
  • Chrome 5+
  • Safari 4+
  • Konqueror 4.4+

However, it’s only verified to work in:

  • Firefox 4 (Win and OSX)
  • IE9+
  • Opera 11.10 for OSX, Opera 11 for Windows
  • Chrome (Win and OSX)
  • Safari 5 (Win and OSX)

This doesn’t mean it won’t work in the rest, just that it hasn’t been tested there (yet). You can load the unit tests (sort of…) in a browser you want to test and let me know about the results. :)

Naice! Can I haz?

As usual, you can get it from Github: Github repo

Credits

Thanks a lot to Max (@suprMax) for Windows testing!


Rule filtering based on specific selector(s) support

2 min read 0 comments Report broken page

I’ve been using this trick for quite a while, but I never thought to blog about it. However, I recently realized that it might not be as common as I thought, so it might be a good idea to document it in a blog post.

If you follow the discussions on www-style, you might have noticed the proposal for a @supports rule to query property and value support. Some people suggested that it should also test for selectors, for example whether a certain pseudo-class is supported. However, you can do that today, albeit in a limited manner (no OR and NOT support).

The main principle that you need to keep in mind is that browsers are expected to drop rules with selectors they don’t understand, even partially. So, if only one selector in a group cannot be parsed, the whole rule will be dropped. This means we can construct selector “tests”, which are use cases of the selector whose support we want to test, that will not match anything, even if the selector is supported. Then, we include that selector in the beginning of our selector group. If all this is unclear, don’t worry, as there’s an example coming next :)

Example

Suppose you want to apply the following CSS (for rudimentary custom checkboxes):

input[type=“checkbox”] { position:absolute; clip: rect(0,0,0,0); clip: rect(0 0 0 0); }

input[type=“checkbox”] + label::before { content: url(‘checkbox.png’); }

input[type=“checkbox”]:checked + label::before { content: url(‘checkbox-checked.png’); }

only in browsers that support the attribute equality selector, the :checked pseudo-class and the ::before pseudo-element. We need to try to think of a selector that includes all of them but matches nothing. One such selector would be #foo[type="checkbox"]:checked::before. Even in supporting browsers, this matches nothing as there’s no element with id=“foo”. We can reduce the test for every rule to conserve bandwidth: For example, we don’t need to include tests for the attribute selector in any of them, since they are present anyway in all three rules. Also, we may eliminate ::before from the second test and we don’t need any test for the 3rd one, since it includes all features we want to test for. To sum up:

#foo:checked::before, input[type=“checkbox”] { position:absolute; clip: rect(0,0,0,0); clip: rect(0 0 0 0); }

#foo:checked, input[type=“checkbox”] + label::before { content: url(‘checkbox.png’); }

input[type=“checkbox”]:checked + label::before { content: url(‘checkbox-checked.png’); }

An important caveat of this technique is that Internet Explorer up to version 7 will split selectors before parsing them, so it will completely ignore our filters :( (Thanks to Ryan Seddon for finding that out).

Disclaimer: The original idea about custom checkboxes belongs to Ryan Seddon, although his code was quite different.


CSS3 patterns gallery and a new pattern

1 min read 0 comments Report broken page

I finally got around to doing what I wanted to do for quite a few months: Create a gallery with all the basic patterns I was able to create with CSS3 gradients. Here it is:  CSS3 Pattern Gallery

Also, it includes a brand new pattern, which is the hardest one I have ever made so far: Japanese cubes. Thanks to David Storey for challenging me about it.

Supported browsers:

  • Firefox 4 (the patterns themselves work on 3.6 too but the gallery doesn’t due to a JS limitation)
  • Opera 11.10
  • IE10
  • Google Chrome
  • Webkit nightlies

However bear in mind that every implementation has its limitations so a few of them won’t work in all the aforementioned browsers (for example Opera doesn’t support radial gradients and Firefox doesn’t support explicitly sized ones).


Invert a whole webpage with CSS only

1 min read 0 comments Report broken page

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](javascript:(function(){var%20style=document.createElement(‘style’);style.innerHTML=‘body:before%20{%20content:%22%22;%20position:fixed;%20top:50%25;%20left:50%25;%20z-index:9999;%20width:1px;%20height:%201px;%20outline:2999px%20solid%20invert;%20}’;document.body.appendChild(style)})();)

**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.


Create complex RegExps more easily

1 min read 0 comments Report broken page

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 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  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=/(?:tops+|bottoms+)?(?:right|left)|(?:rights+|lefts+)?(?:top|bottom)/;

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

self.regex.color = RegExp.create(‘(?:||)’, { 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: self.regex.number }), hex: /^#(?:[0-9a-f]{1,2}){3}$/ });

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

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

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

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

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


Convert standard gradient syntax to -webkit-gradient and others

1 min read 0 comments Report broken page

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.)


Beveled corners & negative border-radius with CSS3 gradients

1 min read 0 comments Report broken page

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 :P


On CSS preprocessors

4 min read 0 comments Report broken page

Lately there has been a rise in the usage of CSS preprocessors such as LESS and SASS, which makes sense given the simultaneous increase of CSS3 usage. I’ve frequently argued with fellow front-end web developers about whether they should be used or not and I decided to finally put my thoughts in writing.

To start, I can fully understand the advantage of using such preprocessors over vanilla CSS3. I hate listing all the vendor prefixes, and not being able to use variables, mixins or nesting just like the next web developer. All this syntactic sugar can simplify your workflow by a great deal and make writing CSS3 incredibly fun. However, I still refrain from using them, and I’ll explain why below.

Losing track of CSS filesize

When I’m writing CSS, I try to keep the filesize as small as possible. I’m not a filesize hypochondriac, I try to balance filesize and readability and I prefer to err on the side of the latter. I’m not one of those people that will use #000 instead of black just to save a byte and I use lots of indents and newlines (later minification takes care of that). However, in cases when the readability impact is small and the filesize impact is large (and minification won’t help), I will do the optimization.

For example, consider the following case: Let’s suppose you have 3 rules (#foo, #bar and #baz) that will both use the same CSS rotate transformation, among other CSS declarations. Using a mixin is simple (using the LESS syntax in this example):

.rotate (@degrees: 10deg) { -moz-transform: rotate(@degrees); -ms-transform: rotate(@degrees); -o-transform: rotate(@degrees); -webkit-transform: rotate(@degrees); transform: rotate(@degrees); }

#foo { font-size: 150%; .rotate(40deg); }

#bar { background: silver; .rotate(40deg); }

#baz { background: white; .rotate(40deg); }

Sweet, huh? And only 370 bytes. However, what the end user downloads is this beast:

#foo { font-size: 150%; -moz-transform: rotate(40deg); -ms-transform: rotate(40deg); -o-transform: rotate(40deg); -webkit-transform: rotate(40deg); transform: rotate(40deg); }

#bar { background: silver; -moz-transform: rotate(40deg); -ms-transform: rotate(40deg); -o-transform: rotate(40deg); -webkit-transform: rotate(40deg); transform: rotate(40deg); }

#baz { background: white; -moz-transform: rotate(40deg); -ms-transform: rotate(40deg); -o-transform: rotate(40deg); -webkit-transform: rotate(40deg); transform: rotate(40deg); }

which is almost double the filesize (600 bytes). It could have easily been this:

#foo, #bar, #baz { -moz-transform: rotate(40deg); -ms-transform: rotate(40deg); -o-transform: rotate(40deg); -webkit-transform: rotate(40deg); transform: rotate(40deg); }

#foo { font-size: 150%; }

#bar { background: silver; }

#baz { background: white; }

which at 290 bytes, is even smaller than the first one. The differences would be even bigger if you had to specify a different transform-origin.

Of course you can still do such optimizations when using CSS preprocessors, but since you don’t have the ugliness in front of you and the file you’re working with remains small, it’s easy to forget and just do what’s easy. You lose sight of the big picture. But it’s the big picture (or big file, in this case ;)) that your users eventually download.

Same goes for nesting: Instead of actually putting some thought into the selectors you choose, you can just nest and let the preprocessor sort it out, usually in the straightforward but unavoidably verbose way.

LESS is better in this aspect, since it also offers a client-side version, so the user downloads the small file you wrote, and all the expansion is done in their machine. However, this has the (big, IMO) disadvantage that all your CSS becomes dependent on JavaScript to work and that your users have to download the LESS code, which isn’t that small: 33KB minified which is way larger than most stylesheets (granted, if you gzip, it will be smaller, but this is true for stylesheets as well).

Maintenance woes

Eventually, CSS will start supporting all this sweetness. Tab Atkins has already drafted a proposal and soon Webkit nightlies will implement the functionality. After that, I think it’s safe to assume that within 2 years Firefox and Opera will also implement the (by then) standard and within 1-2 more even IE. Then we’ll need another 2-3 years to be able to start using it (adoption rates of new browser versions will have increased too). This means that in as little as 6 years, we might be able to use CSS variables, mixins and nesting in vanilla CSS. All the code written for today’s preprocessors will eventually have to be rewritten. Maybe even sooner, since when a standard is published, I think it’s safe to assume (or hope) that the new versions of CSS preprocessors will deprecate their old syntax and start supporting and recommending the standard way, effectively becoming polyfills (which I definitely support). So, coding for a CSS preprocessor today feels a bit like building castles on sand.

Debugging woes (thanks to Jesper Ek)

Preprocessors make debugging CSS harder, since the CSS you see in Web Inspectors like Firebug or Dragonfly is not the CSS you wrote. The line numbers don’t match any more and the CSS itself is different. A lighter form of the same problem also occurs with minifiers, but you can delay using them until you’re done with the site. With CSS preprocessors, you have to use them from the beginning if you want to really take advantage of them.

Also, when I develop my CSS, I want to be able to instantly preview the changes in the file by just refreshing the browser. With preprocessors this becomes harder (although not impossible).

Generic concerns with such abstractions

With every new syntax, comes more effort required by someone to start working on our code. We either have to only collaborate with people proficient in the CSS preprocessor of our choice, or teach them its syntax. So we are either restricted in our choice of collaborators or need to spend extra time for training, both of which are nuisances.

Also, what happens if the preprocessor stops being updated? Granted, most (if not all) are open source, but the community’s interest might shift to something else. Many open source projects have eventually died due to lack of interest. And let’s not forget the law of leaky abstractions

Yes, both concerns are valid for every framework, in every language, but at least PHP frameworks or JavaScript libraries are more needed than CSS preprocessors, so it’s a tradeoff is that’s worth it. For CSS preprocessors, I’m not so sure.

Conclusion & disclaimer

I have to admit that even though I’ve read quite a bit on CSS preprocessors and talked with fellow web developers about them, I don’t have hands-on experience with them. Maybe I will change my mind if I actually do so. Besides, I think that if someone uses a CSS preprocessor carefully, with knowledge of the points mentioned above, it can actually turn out to be beneficial. However personally, I prefer to wait at least until they start supporting the (future) standard syntax, whenever that happens.


WD @media talk subject change

1 min read 0 comments Report broken page

I recently changed my Web Directions @media talk title & abstract to something more specialized. Instead of discussing under-hyped CSS3 features in general I will only focus on one CSS3 feature (more hyped than the ones I was planning to show, but all the hype is only about very basic use cases): CSS3 Gradients:

Mastering CSS3 Gradients

With most browsers adding increasing support, and the simplicity of providing fallbacks for those that don’t, CSS3 gradients are something we can start to use right now. They benefit our users with faster websites and ourselves with more time in our hands to spend in other things, since they are easy to create, edit and update. A very powerful feature that can also be utilized for a surprising number of design effects, even ones that don’t resemble gradients at all. In this talk, Lea will explore CSS3 gradients in great depth and it’s almost guaranteed that no matter your expertise level, you will walk out having learned new things.

I tested a draft of this talk with a meetup group in Oslo (Framsia) and it went very well. I got reviews like “I was amazed that you managed to speak almost an hour of CSS3 gradients and still keep the crowd interested” (thanks Legendre!). Even Bruce Lawson, who happened to be there, told me he didn’t know like 70% of the material presented! :)

I’m looking forward to it since it’s a topic I’m passionate about, and I hope to see you there! Don’t forget that you can use the coupon code WDVEROU when registering to take £50 off the current price.

PS: I don’t like the title very much, so if you have anything more witty to suggest, feel free. ;)


Custom <select> drop downs with CSS3

2 min read 0 comments Report broken page

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. You can easily detect if pointer-events is supported via JS and only apply this it if it is (eg by adding or removing a class from the body element):

if(!(‘pointerEvents’ in document.body.style)) { … }

However, there is one caveat in this: Opera does include pointerEvents in HTML elements as well, but it does not actually support the property on HTML. There’s a more elaborate feature detection script here as a Modernizr plugin (but the code is quite short, so you can adapt it to your needs).

Also, don’t try to replicate the behavior in JavaScript for browsers that don’t support this: it’s impossible to open a <select> drop down with JavaScript. Or, to put it differently, if you manage to do it, you’ll probably be the first to. Everything I could think of failed and I spent hours yesterday searching for a way, but no avail.

References


Checkerboard pattern with CSS3

1 min read 0 comments Report broken page

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.


Incrementable length values in text fields

1 min read 0 comments Report broken page

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.


Convert PHP serialized data to Unicode

1 min read 0 comments Report broken page

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,PREGOFFSETCAPTURE,++offset)) { $number = $matches[1][0]; $pos = $matches[1][1];

digits = strlen(&quot;number"); poschars=mbstrlen(substr(text, 0, $pos)) + 2 + $digits;

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

newnumber=strlen(str); newdigits=strlen(new_number);

if($number != $new_number) { // Change stored number text=substrreplace(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.


Styling elements based on sibling count

1 min read 0 comments Report broken page

The original idea belongs to André Luís, but I think it could be improved to be much less verbose.

André’s solution is like this:

/* one item */
li:nth-child(1):nth-last-child(1) {
	width: 100%;
}

/* two items */ li:nth-child(1):nth-last-child(2), li:nth-child(2):nth-last-child(1) { width: 50%; }

/* three items */ li:nth-child(1):nth-last-child(3), li:nth-child(2):nth-last-child(2), li:nth-child(3):nth-last-child(1) { width: 33.3333%; }

/* four items */ li:nth-child(1):nth-last-child(4), li:nth-child(2):nth-last-child(3), li:nth-child(3):nth-last-child(2), li:nth-child(4):nth-last-child(1) { width: 25%; }

It’s based on the relationship between :nth-child and :nth-last-child. As you can see, the number of total rules is O(N) and the number of selectors in every rule is also O(N).

However, what you really want, is to just target the first element. The others can be targeted with just a sibling selector. With my improvement, the number of total rules is still O(N), but the number of selectors in every rule becomes just 2, making this trick practical for far larger numbers of children:

/* one item */ li:first-child:nth-last-child(1) { width: 100%; }

/* two items */ li:first-child:nth-last-child(2), li:first-child:nth-last-child(2) ~ li { width: 50%; }

/* three items */ li:first-child:nth-last-child(3), li:first-child:nth-last-child(3) ~ li { width: 33.3333%; }

/* four items */ li:first-child:nth-last-child(4), li:first-child:nth-last-child(4) ~ li { width: 25%; }

And here’s a fiddle to prove it:

Yes, I know that with Flexbox and the other layout modules, techniques such as these are soon becoming obsolete, but I think they are still useful right now. I’m also aware that you can emulate this particular example with table display modes, but a) Table display modes have other implications that are sometimes undesirable and b) Widths are just an example, you could come up with other ways to style the elements based on their total count, which can’t be emulated by CSS tables.


I’m speaking at @media Web Directions ’11!

1 min read 0 comments Report broken page

Just a quick note to let you know I’m speaking at this year’s @media Web Directions conference, which will take place during May 26–27 in London, UK. I’m very excited about this, since I always considered @media one of the top front-end conferences in the industry :)

The title and abstract of my talk is as follows:

CSS3 at the Outer Rim

By now most of you know how to use the core CSS3 features in your designs to embed custom fonts and easily create rounded corners, drop shadows, and scalable designs with media queries. But there is still a large area of CSS3 that remains unexplored by most web designers and developers. In this talk Lea will present many CSS3 features that are useful but underrated, as well as uncommon ways of utilising the CSS3 features you already know about, in order to do much more with even fewer images and less code.

Although it’s on the design track, I expect it to appeal to both developers and designers.

You can use the coupon code WDVEROU to take £50 off the current price. ;)

Hope to see you there! :D