Pure CSS Submarine

Background

About six years ago I was working with a very mundane data processing program. While looking into some styling for it I researched all the new features being added to CSS e.g. gradients, transitions, and animations. Also, at this time I realized that it was possible to abuse certain aspects of the CSS pseudo-classes. It was then that I had the completely impractical idea of building a submarine game with just CSS. Fortunately in the intervening six years things have greatly improved. For instance I no longer have to deal with browser prefixes.

Over Christmas I suffered some from JS burnout and just took a break from it. The result, I decided to try my hand at mangling CSS.

Here is the completed project. To go down press tab. To go back up press shift+tab. To fire the weapons appropriate at the different levels press the space.  To detonate the weapon press space again (This last part isn’t fully functional see bottom for details). Works best in Firefox and Edge. For some reason Chrome doesn’t show the waves.

Design

Design is pretty easy for this, lots of linear gradients and grey coloring. To get some of the angled edges I at first was going to use the transparent border trick to get triangles, but using gradients on borders was difficult. So, I found and used a technique that used angled linear background gradients.

The sub design was based on this Wikipedia image and various image searches for trident missiles and mk torpedoes.

Techniques

User Interface

The key to the user interface is two invisible inputs

tab and shift+tab toggle back and forth between the two inputs and space allows you to toggle the checked state.

This means you can use :hover and :checked to perform actions on the sub. Also, very key is the ~ sibling selector. This allows any subsequent elements to refer to the state and react accordingly.

Tail

Submarine Tail

The tail presented several interesting challenges. First was the simulation of the spinning propeller.

First the rectangle is skewed to give it the angled tips. Then we scale the div from full height to 0 and back every .3 seconds. Also, as it gets shorter we lighten the color. This makes it look more transparent in the center. The second challenge was adding the vertical fins.

If you’ll notice this gives the triangular tail, but it also colors the outside blue. Meaning layering is an issue and the vertical fins have to sit adjacent to the edges. This can be done by rotating the :before and :after pseudo-elements to the angle of the triangular tail, but we still want an angle on the fin as well.

After rotating the whole element we again add angled linear gradients. First we need the 20deg angle to get the perpendicular grey gradient (20+70=90). Then we add the blue -70deg angle to create a vertical blue strip that creates the left edge. Finally the -160deg angle finishes off the angled top right edge. Mapping this to the bottom fin was actually easy all that was needed was a negative scaling transform to flip what was already created, the supplementary angle of 70 degrees and 55 instead of -55.

Weapons

Adding the torpedo was not complicated. The design was similar to that of the sub itself. The path was pretty easy well. The biggest complication was getting the z-index and layering correct.

The difficulty with the missile was getting a somewhat natural looking trajectory. I found this code that I was able to tweak to get something that looked close.

Sonar

I have to mention something about the sonar. The effect is really simple and I imagine could be useful in actual web pages e.g. showing an active connection.

To begin with use border-radius:50% to get a circular shape. Add a border on the right side so that it looks like it is coming from the nose cone. Then use animation to scale it and make it fade out the large it gets.

The one thing I originally tried was using the pseudo-elements and the parent element, but since the pseudo-element’s position changes based on the parent I scrapped that idea.

Improvements

First thing that could be improved would be using a CSS precompiler like SASS. Not only would it help with a number of the repetitive linear gradients it would allow me to break this up into smaller units. This was one of those projects that you start out just hacking away at and suddenly find it would have been much better to use some type of modularity.

Another big disappointment was the fact that I couldn’t get the weapons to explode. The main problem is when you cancel the animation I want to use an animation to make the weapon disappear and a transition to make the weapon wait for the explosion and then jump back to starting position.

Firefox it works great…the first time. After that it acts like all the other browsers and as soon as you toggle the space bar again the whole element jumps back to the starting position with no pause. Either this is the same bug in every browser or Firefox has a bug by letting it happen the first time.

The problem I addressed in this Stackoverflow question is the fact that when you have an animation it needs a start and end point. If an animation gets canceled in the middle, how do you smoothly transition back to the starting state (Or in my case wait and jump back). A return animation doesn’t work well because you don’t know the starting position. If whatever you are trying to do can be done with transitions to both states then its not a problem. But, if you are trying to create say a torpedo path you can’t just use a transition.

Another thing I couldn’t seem to work around is the the up animation occurring when you load the page and anytime you switch back to it from anything else. Because you have to use an animation for when the input is active and another one for when it isn’t, the sub is always going animate when you switch back to the page and the input receives focus again.

Some other animation improvements would be the path of the missile. I didn’t find many tutorials on creating ballistic trajectories using CSS animations. Also, a more detailed wave animation would be nice, but I wasn’t sure how to tackle that one. Also, since I didn’t get the explosion to happen I didn’t add a shaking animation, but it would be relatively simple to add an element before the sub that contracts and flexes after an explosion to simulate the concussive force. Perhaps possible, but more difficult would be adding splashing water. Related to the weapons would be the trails left by the missile and torpedo, but I didn’t have time see if that was even possible.

Conclusion

I hope you found this interesting if not practical. I have ideas for further abusing CSS pseudo-classes that I may explore in the future. Also some credit is due to several resources I used repeatedly while creating this.

Pure CSS Modal Alert

My previous post was about CSS tooltips. Which after the fact I realized that MDN had a similar tutorial. In this post we will attempt something slightly more complicated – modal alerts.

jsfiddle example

Code

The idea is similar to that of the tooltip. Once you have the alert up use :hover on a full screen pseudo element to keep it there.

In this particular example we are showing an image in the alert.

The key here is to display content on the content hover and on the modal click.

But when we click the content we want to switch to display:none

Advanced Usecase

This next example is still a work in progress, but using these ideas combined with CSS transitions we can do some pretty cool stuff with just CSS.  The idea of this demo is an info button in the corner that has a cool animation when it appears and disappears.

The difficulties of this are dealing with transitions that mean leaving content on the screen that interact poorly with the :hover pseudo class.

I’m sure there are better animations that could be done e.g. something like the minimizing of an application in Windows or Apple. Also, I haven’t quite figured out how to do it with only two elements if anyone finds a clever workaround I’d be interested to know what it is.

Caveats

Again all the caveats from before apply. This is not touch screen friendly. Now it might be possible change using :focus, but that is dependent on if you want to add the complexity.

Another problem is  moving off the browser content will also cancel the alert.

 

Pure CSS Tooltips

CSS Frameworks

One ironic thing about CSS frameworks is many require a JS library to work (And then sometimes they also require Jquery on top of that). One of the things they like to use JS for is tooltips. Which as I’m going to show is not always necessary.

Here is completed jsfiddle example.

Code

Tooltips are actually very easy to do with just CSS. Lets look at an example using tooltips for definitions. Lets say we have a sentence with a word we want to define.

So we have a sentence with a tooltip and a message. All we need now is three CSS rules.

The main trick of this is .tooltip:hover works even when hovering over children. So as soon as you make .message visible as long as the mouse stays on the message it will stay visible.

Improvements

This is a very simple example. Obviously adding shadow effects and possibly some animations would make it more visually appealing. Also, if you wanted to use superscripts similar to Wikipedia. You would need to remove the dotted underline and style accordingly.

A more advanced pure css example Wikipediaesque tooltip.

Caveats

There are several caveats however. First is the lack of support for touch input. This could be added by using links or giving a tabindex and the :active pseudo-class. But this means that clicking on the word will not remove the tooltip until you click somewhere else. So whether this is viable is dependent on the use case.

The second problem is positioning. JS can be used to measure whether the tooltip should be above/below or to the left/right of the target. CSS Doesn’t do a good job of handling this. This may or may not be a problem if used in a central column of text it probably won’t be much of a problem, and if you know for a fact it needs to float another direction you can add a direction class to your tooltip that handles it. The problem is there may be sometime where you don’t know exactly where the target it going to end up in relation to the rest of the page. So again it depends on your use case and on your design.