Category Archives: CSS

Pure CSS ‘tags’—ala SoundCloud

For the recent realignment I wanted to emulate the cute little ‘tags’ that sit below a track on SoundCloud.

I wanted to try to do as much as possible using CSS alone—without background images, too many extra elements, or general hackery. Ideally, the markup would be:

<a href="…">Tag text</a>

There are lots of posts around the interwebs about CSS triangles, but it’s hard to find a concise tutorial for putting an arrowhead on the end of a box. So I started by pinching borrowing a technique Ben pulled together for a site we were working on.

I noticed the negative margins were not playing nicely with iOS so I switched to relative positioning to offset the arrowhead. This also simplifies the padding/margin calculations, makings the final solution easier to tweak.

.tags a {
	float: left;
	background: #c5c5c5;
	color: #fff;
	text-decoration: none;
	margin: 0 0 10px 18px;
	padding: 2px 10px 1px;
	border-top-right-radius: 3px;
	border-bottom-right-radius: 3px;
	position: relative;
	transition: all .25s linear;
	text-shadow: 0 1px 1px rgba(0, 0, 0, 0.4);
	white-space: nowrap;
	line-height: 21px;

.tags a:before {
	content: "";
	border-style: solid;
	border-color: transparent #c5c5c5 transparent transparent;
	border-width: 12px 13px 12px 0;
	position: absolute;
	left: -13px;
	top: 0;
	transition: all .25s linear;

Hover states need to cover the anchor background and the triangular border colour…

.tags a:hover {
	background-color: #39F;
.tags a:hover:before {
	 border-color: transparent #39F transparent transparent;

For the ‘hole’ punched in the tag, I thought I’d have to rely on a background image. Ben made a good point about reusing the bullet from a list item (which worked, with some negative margin trickery).

I finally thought to check the approach that soundcloud actually take and I was pleasantly surprised… clean minimal markup and a CSS-only solution!

Why didn’t I check their implementation sooner??

In the end, I borrowed their approach for the hole…

.tags a:after {
    background: none repeat scroll 0 0 #FFFFFF;
    border-radius: 50% 50% 50% 50%;
    box-shadow: 0 1px 1px #737373 inset;
    content: "";
    height: 5px;
    left: -1px;
    position: absolute;
    top: 10px;
    width: 5px;

Which ends up looking like this…

Screenshot of two tags in situe next to a blog post

Hats off to the designers and front end devs at soundcloud, they know what they are doing!

Posted in


Finally got around to fixing my corrupt zip file issues. Fresh and flawless zip files are now available for the latest versions of all widgets and plugins.

BTW the compact content plugins have been updated with a bunch of small fixes (IE6 benefits the most from this release). See new examples, downloads and changelog for version 3.5.

Posted in

Transformer transformed

In light of increasing browser support for CSS3 media queries, I have spent some time today updating the transformer layout plugin in an attempt to achieve a seamless integration of the new CSS3 functionality for including stylesheets dependent on the browser’s current viewport width.

Most media query implementations I have seen use px units to define min-width and/or max-width limits. This approach is fine for browsers that zoom, but less than ideal for browsers that don’t. Not a huge issue when you consider that the modern browsers that support media queries all zoom by default! But for transformer layout to retain support for older browsers that don’t zoom, em units would be the way to go.

Firstly, I ran some tests of current browser support for CSS3 media queries using em units, the results were:

  • Firefox (3.6.2) and Opera (10) support media queries with em units and load the correct stylesheet after zoom level change.
  • Chrome (4) and Safari (4) support media queries with em units but fail to load the correct stylesheet after zoom level change.
  • IE (6, 7 and 8 ) do not support media queries at all.

Alexander Farkas has a nice solution for detecting media query support and supplementing for non-supporting browsers but unfortunately it doesn’t support em units or compensate for Safari and Chrome’s insufficient handling of zoom level changes.

The new transformer layout plugin takes Alexander’s great work and rectifies both of those limitations so now it can be used to achieve an approach to layout optimised for all browsers, devices, resolutions, text sizes and zoom levels.

Posted in

Accessible UI buttons

Today I updated the compact content widgets such that assistive technologies that don’t appropriately support the title attribute are still able to access the text expansion of each button on the User Interface (UI) for the widget.

While doing this, I thought I should take the time to document the updated approach I use when creating groups of UI elements for my DHTML projects.

Let me know your thoughts.

Posted in

Large content, an eternal golden conundrum

I’ve always been a fan of flexible layout and trying to avoid introducing horizontal scrollbars whenever possible. Large content however poses an eternal conundrum: How to accommodate large content in tight spaces?

Some web designers like to lock a page design to a fixed width (or set a minimum width) forcing a horizontal scrollbar at lower resolutions for the entire site. This approach however does not accommodate some of the larger content types and I feel its a missed opportunity to maximise accessibility. A flexible layout allows your design to be adaptable and optimised for the device/resolution currently being used to view it.

I’ve been playing with some ideas that can be used in conjunction with any layout to accommodate wide content as easily as possible at lower resolutions.

With this example, trying resizing your browser window, make it fairly narrow.

  • Large content such as tables should expose a horizontal scrollbar just below the table at low resolutions.
  • Images will be scaled down to fit the width available automatically. Scaled images also gain the ability to zoom to full size on click (which also introduces a horizontal scrollbar for the image).

The code is not production ready yet (IE6 in particular needs work) but it should give you an idea of where it’s heading.

Let me know what you think!

Posted in