My newest article on Smashing Magazine’s coding section is for the geekiest among you. It’s about how you can pack long lists of boolean values into a string in the most space-efficient way. Hope you enjoy it 🙂
I always loved Github’s ability to publish pages for a project and get the strain out of your server. However, every time I tried it, I struggled to keep the gh-pages branch up to date. Until I discovered the awesome
Usually my github workflow is like this:
git add . git status // to see what changes are going to be commited git commit -m 'Some descriptive commit message' git push origin master
Now, when I use gh-pages, there are only a few more commands that I have to use after the above:
git checkout gh-pages // go to the gh-pages branch git rebase master // bring gh-pages up to date with master git push origin gh-pages // commit the changes git checkout master // return to the master branch
I know this is old news to some of you (I’m a github n00b, struggling with basic stuff, so my advice is probably for other n00bs), but if I had read this a few months ago, it would’ve saved me big hassles, so I’m writing it for the others out there that are like me a few months ago.
Now if only I find an easy way to automate this… 🙂
I wrote this script while at the airport travelling to Oslo and during the Frontend 2011 conference. I think it’s amazing, and it makes authoring CSS3 a pleasure.
Hope you like it!
A week ago, I released Chainvas. It was a spin-off script I wrote while developing my cubic-bezier tool, to make using the Canvas API a bit less painful. However, unlike similar attempts to make the Canvas API chainable, most of my code was written in a very generic manner, and was actually able to make every API chainable. However, when I released it, even though I mentioned that it can be used for other APIs and provided some examples, practically everyone that shared the link on twitter or other means (thank you .net magazine for the newsletter mention btw!) focused on what Chainvas did for Canvas.
Actually, while using Chainvas myself, I found it immensely more useful for chaining DOM methods and setting multiple element properties at once. Chainvas had a lot of potential, that most people were missing. And then it dawned on me: I should modularize the library! A generic chaining library at its core and additional modules for making the different APIs chainable. And I did it.
On the way to that, I added IE8 compatibility, and tested in many other browsers, thanks to Browserstack. I actually found that Chainvas’ core even works in IE6! I also wrote unit tests, a much more extensive documentation, added a script generated table of contents and designed a logo and a Chainvas pride banner.
Also, since it was now modular, it needed a build script. I badly wanted to make this client side, so I followed this architecture:
- Every module is included in chainvas.js and chainvas.min.js, along with a header comment that follows a specific syntax.
- The user selects a compression level and then, the relevant script is downloaded through XHR and split into parts according to the module headers. Then a module list is generated with checkboxes for the user to select the ones they want to include.
- When the user checks and unchecks those checkboxes, the URL of the download link changes to a data URI that contains the script.
A few days ago, I had a talk at a conference in Zurich (I’m going to write more about it in another post). The talk was about “10 things you might not know about CSS3”. The first of those things was how you can do bouncing transitions with cubic-bezier() instead of an easing keyword. As usual, my slides included a few live demos of the functionality, in which I edited the cubic-bezier() parameters and the audience could see the transition produced.
However, in the case of cubic-bezier() that’s not enough. No matter how much you see someone changing the parameters, if you don’t picture it in a 2D plane, it’s very hard to understand how it works. So, the night before, I searched for a tool I could use to show them how bezier curves are formed. I found plenty, but all of them restricted the the coordinates to the 0-1 range. I’m not sure if the cause is ignorance about the spec changes or that Webkit hasn’t caught up with those changes yet (but it will, soon). The only one that supported values out of range was this one from the Opera Dragonfly developers, but I found it kinda impossible to adapt.
For my talk, I tried to adapt one of them but it was late so I gave up after a while and ended up just showing them a screenshot. And the day after the talk, I started adapting this to my needs (ever tried coding at a conference? It’s awesome, you get to ask questions from very knowledgeable people and ger replies straight away). And then I started cleaning up the code, changing how it worked, adding features. At this point, I think the only thing that’s left from that tool is …the HTML5 doctype. After 3-4 days, I finished it, and got it its own domain, cubic-bezier.com (I was surprised it was still free).
So, in a nutshell, what makes this better?
Lots of things:
- It supports y values out of range, as per the latest version of the spec (and shows a warning for Webkit)
- It’s fully accessible from the keyboard
- You can move the handles not only by dragging but also by clicking on the plane or using the keyboard arrow keys
- You can mouse over the plane and see the progression and time percentages that correspond to every point
- You can save curves you like in your “Library” (uses localStorage to persist them)
- You can import and export curves to/from your library to share them with others
- You can share a permalink to every curve. For example, here’s a bouncing transition (FF & Opera only)
- You can compare the current curve with any in your library, setting the duration yourself
- Custom favicon that reflects the current curve
Cool stuff used
Given that this tool is not only for developers, but for badass developers that care about stuff like cubic-bezier(), I think I can safely assume they’re using a top notch browser. So, I went crazy with using cool modern stuff:
- HTML5: Canvas, localStorage, History API, range inputs, oninput event, output, classList, data- attributes
- ES5: Accessors, Array#map, Array#forEach
- Selectors API
- CSS3: Transitions, gradients, media queries, border-radius, shadows, :in-range pseudoclass, box-sizing, transforms, text-overflow
So far, I’ve tested it in modern versions of Chrome, Firefox, Opera and Safari and it seems to work. I haven’t tested it in IE10 (too lazy to open vm), although I want it to work there too, so if it doesn’t let me know. 🙂
It’s definitely not the first time someone writes a script to make the canvas API chainable, as a quick Google search will confirm.
However, I think my attempt has merit, because it’s not really focused in chaining canvas methods, but just about every API you use it on and because it’s super small, only 1KB!
Thought I’d let you know that my Smashing Magazine article with that title was published today. It discusses why, how, when and where to report browser bugs, as well as how to make a good bug report.
Get comfortable and make a big cup of coffee before you dive in, as it’s quite long (4000 words).
steps() is a relatively new addition to the CSS3 animations module. Instead of interpolating the values smoothly, it allows us to define the number of “frames” precisely. So I used it to create headers that have the well-known animated “typing effect”:
As you can see, the number of characters is hardcoded in the steps() function, but that’s the only place. Everything else is totally flexible. Apart from the font: It has to be monospace, so that every character has the same width.
Also, this particular way requires a solid background and an extra <span>. You can avoid these limitations by directly animating the width of the heading itself, but this requires a fixed target width hardcoded in the animation, so 2 things that need to be changed for every heading:
If you’re having trouble understanding how it works, take a look at this simpler example, with just the cursor.
Gecko (Firefox) and Webkit only at the moment, since other engines haven’t implemented CSS animations yet. However, both examples degrade very gracefully in other browsers (IMO at least).
Whenever I wanted to convert a CSS named color to RGB, I used to open the CSS3 colors spec in a new tab, search in the page and copied the values. Every time it felt even more tedious. I didn’t want to search in long tables, I wanted to type the color somewhere and get the values back, in an easy to copy format. So, after yet another color lookup earlier today, I decided to scratch my own itch and do it myself.
Of course, I didn’t plan to include a whole database of CSS colors in the website. My idea was much simpler: Use the named color to draw a rectangle in a <canvas> and then read the R,G,B values through ctx.getImageData().
I got the core functionality done in under 10 minutes, so I started adding stuff. I added a hex and HSL representation, I used canvas.toDataURL() to get a data URI of the rectangle and use it as a dynamic favicon*, I made the colors sharable and bookmarkable by using an old-fashioned hash. Also, I realized it actually supports any CSS supported color represenation by design, not just named colors.
Regarding the color conversions themselves, I took extra care to avoid redundancy. So values < 1 don’t have leading zeroes (.5 instead of 0.5) and when the hex color is in the format #xxyyzz it gets converted to #xyz. When it’s an RGBA color, it still converts it to hex, since those values will be supported in CSS4.
Since it’s for developers, I didn’t bother at all with fallbacks.
Cool stuff used:
- HTML5: canvas, autofocus, output, oninput event, hashchange event
- CSS3: gradients, media queries, box-sizing, background-clip, border-radius, shadows, RGBA
- ES5: Array#map()
- Selectors API
The reason the input’s border appears weird on Webkit is this long standing Webkit bug. Also, for some reason my nice dynamic favicons don’t display on Firefox, although they display fine in Webkit and Opera.
*Thanks to @milo for giving me the idea of using a dynamic favicon