Archive for the ‘CSS’ Category

CSS Hitbox Detection

Wednesday, October 24th, 2012

Note: Read this to the end before you get too excited. This is an interesting CSS hack/exercise, but it faces a major hurdle that limits its applicability.

File this under: cool tricks with CSS that might be a poor use of your time, or might be more awesome than two unicorns doing synchronized backflip space diving.

Over the weekend while brushing up on CSS animations, I had an errant thought involving how the brains of certain types of flies operate.

Which I won’t go into for now. Let’s just say that nature is weird, providing very disparate solutions to the same problem. (In the case of the flies it was how they think.)

The relation to what I was doing at the time is that we’re in a situation where we can animate elements in a browser with the aid of Javascript, or we can now do it with just CSS. I was exploring the range of wacky things I could accomplish with pure CSS, sans Javascript. One of the interactions I wanted to see if I could accomplish was hitbox detection.

In video game programming, hitbox detection is used to determine when one moving element (like Blinky the ghost’s ectoplasmic tendrils of love) touches another moving element (like Pac-Man’s glorious, circular body.) And once that event is detected, the game then causes something to happen. (In the family-safe industry of 80′s arcade games, this means that Pac-Man dies a horrible death, questioning the futility of his existence. In my fevered dreams it would instead result in an erotic love scene of the Pac-Man/Blinky slash variety. Which, I think we all agree, would make for an excellent arcade machine hack.)

We’ve established that CSS can animate objects. But detecting a collision between two of them? Impossible!

Actually…

CSS does possess some rudimentary event detection based around the mouse interacting with page elements. :focus, :checked, :hover, etc. Most of them require users to actively do a discrete event, which is less useful for actively polling for something like the collision between two objects in real time.

:hover, however, provides us with a bit of a possibility. The mouse is just hanging out there on the page, doing its thing. It’s typically hovering over something. Can we make that work for us?

Hover over what?

The mouse hovers over one element at any given point in time, which triggers the :hover pseudo-class for CSS on that element and any of its parents, all the way up to the root.

Let’s assume a very simple problem situation which we’ll be turning into this demo. We have a stationary ‘avatar’, which for the purposes of our demo is a green circle sitting in the middle of the page. We also have an animated ‘mob’, which we’ll render as a black square. The mob is animated to sweep horizontally back and and forth across the page underneath the circle.

What we want to do is detect when the mob passes under the avatar in a simplified, horizontal-only collision detection.

We’ll want this to happen regardless of where our mouse is, which presents a problem. We can’t be hovering the cursor over the avatar, so how will we know when the mob lines up with us?

Sensors

What we want is the ability to detect an overlap at any point in time, regardless of the mouse’s position. To do this, we’re going to create a grid of invisible elements that are aligned around both the avatar and the mob. In our demo, we’ll call the ones attached to the avatar .switch, and the ones attached to the mob .sensor. We’re going to create enough sensors on each side of the elements so that regardless of where they are on our page, the mouse can be hovering over a sensor for each of them. In our case we’re only detecting for a horizontal overlap, so our sensors are as tall as the page. In a situation where we’re worried about vertical overlap, we’d be creating a grid of squares, greatly increasing the amount of discrete sensors we’d be making.

The avatar is stationary, so its sensors can remain stationary with it. The mob is not, so its sensors will have to be animated as well to follow its movements.

Double Hover Detection With Pointer-Events

The reason we’ve made all these sensor elements is to help us detect the avatar and mob overlapping regardless of where the mouse is. Each sensor grid is aligned in space around their respective icon, so when the mouse lines up over both the avatar’s sensors and the mob’s sensors of the same corresponding position, we know that where the avatar and mob are, they too are overlapped. (So, for example, if the leftmost avatar sensor and the leftmost mob sensor are both under the mouse, we can know that the avatar and mob are also overlapped).

Of course, the problem is that CSS can’t detect if the mouse is hovering over more than one element. The first one it encounters interrupts detection on the others.

Pointer-events is a CSS property that I don’t see discussed much, but that proves to be very convenient. It interacts with SVG in all sorts of strange ways, but with ordinary markup and CSS it still has two options. When set to “auto”, the element interacts with the mouse as desired. When set to “none”, the element no longer interacts with the mouse at all, becoming ‘transparent’ to mouse events. Hovers, clicks, it completely disregards them, and the events pass under it to whatever element is beneath.

We can exploit this to provide a sort of double hover detection.

In our demo, we make sure that all our .switch elements for the avatar’s sensors are set to a low z-index, and that the .sensor elements of the mob’s sensors are set to a higher z-index, but that .sensor also has been set with pointer-events: none. We also make sure that our .switch elements come earlier in our markup than the sensors.

.switch { z-index: 1; }

.sensor { z-index: 2; pointer-events; none; }

We then give .switch a rule for when it’s hovered over that causes its corresponding .sensor to regain its pointer-events (and keep it as long as the mouse is over it). In my demo I’ve given each sensor/switch pair a specific class that corresponds with each other. So for the leftmost pair we’d see a rule like this:

.switch.s1:hover ~ .sensor.s1 { pointer-events: auto; }

.sensor:hover { pointer-events: auto; }

This then causes the .sensor in question to be able to interact with the mouse. Since it has a higher z-index than .switch, it will then catch the mouse’s attention.

If at any point in time .sensor is being hovered over by the mouse and has its pointer-events: auto catching it, this means that it is also overlapping with the corresponding .switch. At which point we can say that we know that the mob and avatar are overlapped. So all we need now is to create a rule that acts on the hover event for .sensor. In this case, we’ll be turning the avatar red to show the event.

.sensor:hover ~ #avatar { background: red; }

Don’t Pop The Cork Yet

Victory!

Well, sadly, no.

I made this demo while using Firefox. And current builds of Firefox are very distinct from Webkit and Opera in one very crucial fashion: Firefox actively polls the mouse to determine if hover events are occurring even when the mouse is holding still. So if an animated element (like the mob or its sensors) pass under the mouse, it triggers :hover.

However, in these other browsers, they only bother polling for :hover when the mouse is being used (moving it about, clicking, scroll-wheel, etc). Otherwise, it stops looking and any moving elements passing under it don’t catch the :hover.

So here’s my demo of CSS Hitbox Detection. If you check it in a current Firefox build, you’ll see it working. If you check it in any other browser, you will have to keep wiggling the mouse about to make it work. It also appears that nightly builds of Firefox no longer support this, although I don’t know if that’s by intent or not.

I’ve used pretty big sensor boxes in the demo, as I’m only doing a proof-of-concept here. As such, there can be very significant overlap before the collision is detected. In normal circumstances you’d want your sensors to be as tiny as possible (and therefore have tons of them) to provide a much quicker detection.

As it stands, without the support of actively polling for hover, this isn’t useful for any scenario that requires real-time polling. But it may have other useful applications in an on-user demand. (It would be, for example, bad for a CSS-only Pac-Man game [which would be a nightmare in its own right], but might be usable in a situation where you click a button at a specific point to see if two elements are overlapped).

Notes

Here’s a pared down test of the use case of how browsers handle hover when the mouse is stationary when elements move under it.

Here’s a message by Eric Meyer on www-talk about the issue it brings up.

Thoughts? Workarounds? Uses?

So, CSS Hitbox Detection can exist. But due to how browsers support the :hover event, it may only have a narrow band of application. Obviously this is the sort of interaction that would be better handled by JS (which I knew all along, but was curious to see if a CSS alternative could be made to work).

That said, I’m just one guy with just one brain. I may have overlooked a workaround, or might be failing to see ways this would apply to something really cool despite it’s apparent limitations. Do any of you have thoughts? Ideas? Applications? Please let me know!

Vindaloo Fart

Thursday, February 9th, 2012
CSSquirrel #92: Vindaloo Fart

Featuring Remy Sharp, Tantek Celik and Bruce Lawson, today’s comic would make the perfect premise for a sitcom. I think “Three Developers and a Squirrel” would have a very nice ring to it. The comic also looks at the stinky mess we’re going to put ourselves into if we fail to recognize the problems of the past so that we can avoid repeating them.

In a move that threatens to undo over a decade of hard work to drag web development out of the horrors of the “Great Browser War” and educate developers to make forward-compatible, standards-compliant websites, the CSS Working Group recently discussed the idea of all browsers adopting -webkit CSS properties. Yep, you heard that right. IE, Opera, Firefox… all using -webkit properties.

This step appears to be intended to guarantee that their browsers will properly render websites being made by short-sighted developers who only bother using -webkit properties for advanced and experimental features in their websites even when the other browsers have their own test implementations such as -o, -moz and -ie.

Short version: They’re considering giving up and handing the browsers of the world over to a bunch of standards-blind morons for short term compatibility gains in exchange for long term problems that will make the current version of Webkit be the IE6 of tomorrow.

I’m not a member of the old guard. In the nineties I was in high school and pretending to be in college while making personal websites that were just short of visually hideous but definitely counted as nauseating. I didn’t know better. But thanks to the efforts of too many dedicated and educating web developers to name I was exposed to the concept of “web standards” and went about the process of learning how to do things properly.

I also landed a sweet job at Mindfly and became a member of the professional web world. All thanks to web standards.

As someone who’s been working on websites professionally for the past five years I’ve had my share of struggles with IE6 compatibility. I hate that browser more than I hate most other things on the planet. Intellectually I know it was the bee’s knees in its era. I don’t care. Its era was a long time ago and being forced to keep sites compatible with it due to the lack of standards in its era is a direct cause of hundreds of hours of suffering on my part. I’m grateful that it is now all but extinct, letting me concentrate on dealing with modern or near-modern browsers with a lot less cussing, sweating and crying.

As it stands now, Webkit is a pretty decent browser engine. Chrome is snappy. I like it. I’m using it right this second. But it’s also only as good as it is today. If we stop bothering to properly style our websites with a forwards-compatible approach, using all available browser extensions for experimental properties as well as the non-extension version of the properties for when they becomes available, then we’re daft. We will be putting ourselves at risk of making today’s Webkit the rotting zombie in the room that we’ll be screaming at in terror ten years from now. We, or developers after us, will be wasting countless hours and drinking more heavily in response to dealing with thousands of poorly-made websites that require compatibility with the -webkit properties we shortsightedly hung everything upon.

We need to stop this.

Need more information? Need inspiration on how to help? Lucky for you I’ve got a list:

  • Read Daniel Glazman’s Call For Action. He’s co-chair of the CSS Working Group, and he knows that this is a very bad thing that needs to be stopped. He even suggests how to do it.
  • Also read Remy Sharp’s article on the topic and his suggestions on how to help.
  • Take direct action and help Chris Heilmann Pre-fix the Web, rooting out Github projects that have gone down the dark side and get them forked back into the light.
  • Get Bruce Lawson’s perspective on the vendor prefix issue, taking advantage of the wisdom he’s gained in trying to educate against this exact sort of problem. Also see the first reference of the dreaded vindaloo fart.
  • And please read Eric Meyer’s pessimistic, but perhaps realistic, assessment of the issue in Unfixed.

Whatever you do, don’t be apathetic. Don’t think to yourself that -webkit only sites are professional or even remotely acceptable. Because they’re not. It takes very little effort to guarantee forward-looking, cross-browser websites with the vast majority of most modern CSS properties. Doing anything less for the sake of ease is lazy, unprofessional, and going to cost someone a lot of money and effort in the future.

If you do decide to only use -webkit prefixes, watch out, because Bruce Lawson will vindaloo fart on you.

Comic Update: So Cold

Tuesday, September 6th, 2011
CSSquirrel #86: So Cold

In a perfect world, Ethan Marcotte would star opposite of me in a web design-themed, buddy cop action comedy called Beep and the Squirrel.

Actually… I’m writing that one down, just in case.

Until that glorious moment, I’ll enjoy his raw intellect and seasoned wit while envying his creative talent in a suitably stalker-like fashion. (Unless you’re reading this, Ethan, in which case I assure you that I am in no way digging through your refuse bins looking for cast-off brilliant ideas and toothbrushes.)

While we’re in the vein of borderline creepy idol worship, I’m going to agree with Ethan’s succinct tweet on the W3C’s CSS Conditional Rules Module Level 3 Working Draft (which I’ll reduce to the much easier to remember abbreviation “CCR Module”, hereafter nicknamed the “More Cowbell” document). I feel cold.

I’m still perusing the document. Although any judgement leveled while shooting from the hips (hello, ladies) is bound to be rife with bad summaries and skewed views, in my opinion the module doesn’t seem to solve any problems that aren’t already being solved in a better fashion by good CSS practice or other techniques. It’s a lazy man’s shortcut to “supportin’ olla them thar browsers”.

As Dylan Wilbanks said, these aren’t the conditionals I’m looking for.

Just look at @supports, for the love of cheese (or dairy-free cheese alternative for vegans and the lactose intolerant). It lets you test if a browser supports a feature, before (in their examples) you then go and use the feature. What? How bizarre is that? I know in their examples you can get far trickier with not and or and doogie howser, but seriously?

When it comes to the problems that CSS is supposed to solve, although @supports and its ilk would work, they seem to encourage bad or unnecessarily laboriously bloated CSS documents instead of streamlining the process. And when it comes to @document I believe that the authors are trying to make CSS solve problems it wasn’t intended for.

Look, if you’re trying to get your CSS to be flexibly supported across different browsers and devices, I recommend checking out Ethan’s Responsive Web Design, or at least actually using your skullmeat instead of slapping shoddy shortcuts into your CSS. Capiche?

What the font is going on?

Friday, September 2nd, 2011

This is a general request for assistance regarding a strange font-related error.

AKA: my brain desperately needs your brain’s help.

I’ve recently added embedded fonts to this site, making use of the lovely @font-face to kick things up a notch. By and large, I’ve been rather pleased with the results. However, I’ve encountered an unusual rendering bug that I’ve never seen before and am having very poor luck locating a solution for on the web.

In short, on some Webkit browsers, some (but not all) of my readers are getting a strange text-overlapping glitch with anchor elements. I can reproduce the problem some (but not all) of the time on Chrome (13.0.782.218) in Windows 7. It seems most of the people experiencing it are using Safari on Lion or iOS, or occasionally Chrome. Which leads me to believe it’s a Webkit-related issue.

Here’s a screenshot of the issue, provided for me by reader (and man of fine taste) Alan Hogan. Additionally, you can just look at this page and if you see any funny text overlaps with anchors, congratulations, you’ve found the bug. I’ve used @font-face with plenty of client websites, and have yet to see a link behave like this before, so I’m a bit surprised at its sudden appearance here. At any rate, I’ve been stumped so far in solving it. (I’m even more stumped at it’s infrequent appearance for me in Chrome).

Stephanie (Sullivan) Rewis suggested in a tweet that it might be related to the difference in size between the text first loading in the default, non-@font-face font and then the @font-face snapping into existence. That seems fairly on-target, but it hasn’t helped me figure out how to correct what Webkit is doing wrong.

If you’ve encountered something like this before and have a solution, I’d love to hear it. Thanks in advance.

Firefox 3.6, box-shadow & transform

Friday, March 18th, 2011
The Forest Browser Friends posing together for a photo.

As long as you’re not on a legacy browser, to the left you’ll see an image that is rotated 90 degrees.

If you’re using the current version of Firefox (3.6 as I write this), you’ll also notice a rather unpleasant visual effect on the box-shadow, which isn’t properly surrounding the rotated image like it should be.

I came across this by accident while working on some 2d transforms for a series of photos in a client’s project. I didn’t catch it at first because it only happens somewhere between 82 degrees and 108 degrees (and the direct opposite around 262 degrees to 278 degrees). I might be off by a degree or two, but that’s about the range where the shadow sheers off and snaps down to the picture’s height in its original orientation.

I’ve got a test case here. You’ll note Chrome, Safari, Opera and Internet Explorer (yes, even IE) are doing it right in their current versions. Only Firefox isn’t.

Considering how long Firefox has been implementing transforms in comparison to Internet Explorer (infamous inbred step-child of the browser market), this is really disappointing. It’s details like this that are slowly costing me my love for the flaming-tailed fox.

The bug is fixed in the Firefox 4 beta, thankfully. But that begs the question, how much longer do we need to wait for Firefox 4 to release?