"Event" is a quite diffuse term. It is something that happens unpredictably, we need to "listen" (wait) for it when we want to act on it. For example, operating systems generate events when you use mouse or keyboard.
Disambiguation: in the Java world, events also could be understood as a method-call on 0-n objects that implement a certain listener-interface and have registered for being notified. This is an event abstraction, used to implement loosely coupled parts of an application. The event dispatching mechanism then could be replaced by e.g. network communication at a later time.
Web-pages send events to JavaScript listeners that have registered themselves by calling browserObject.addEventListener(eventType, listenerFunction)
, for example
window.addEventListener('scroll', function(event) { console.log('scroll event '+event); });
But we can not register CSS event listeners. Can we?
You may have seen "Pure CSS" solutions. These actually react upon user input events and alter the page accordingly, for example by opening a menu. And there is no JavaScript in that page that does this! So how does this work?
The idea is to define a CSS-rule that is fulfilled sometimes when a certain state is obtained. For example, when the mouse hovers a certain element (= state), we want to make its font bold. We can detect state changes using CSS pseudo-classes. These are the trailing optional :xxx expressions in CSS selectors(not to be confused with pseudo-elements, which are ::xxx).
Following page defines different colours for active, focus, hover, target
pseudo-classes. Paste the page into some file and view it by using the file:///
protocol in the browser address line. Move the mouse in and out the page, over elements, click on elements, and watch how pseudo-classes change the page.
1 | <!DOCTYPE HTML> |
You can find a list of pseudo classes at many places on the internet. Really useful for animating web pages are only few:
:focus
... becomes true when a focusable element is clicked:target
... becomes true when a hyperlink pointing to an internal target is clickedBut even these leak:
:focus
pseudo-class actually gives you a mouse click for input-elements like a button. You can then open a menu. But when the user again clicks to the button, you can not close the menu through CSS. Just a click elsewhere on the page will release the :focus
state. Finding out this is unfortunately up to the user. :target
, you need to define hyperlinks. The browser would scroll down to the link's internal target element as soon as it was clicked, which may not be what you intended. :target
, the internal link-target will appear in the browser address line, and the browser's "Back" button then would not do what the user expects. Pure CSS solutions mostly need getting used to, which is not an option in our world of increasing comfort. I do not know your usability preferences, but hover-menus are definitely not what I consider to be ergonomic, they are too intrusive.
:focus
PopupCatching a click on a button provides the opportunity to make an element visible that was invisible before. Mind that only few HTML elements are initially focusable: input, select, button, textarea, iframe, a
("anchor", the hyperlink element). But you can make any element focusable by adding the tabindex
attribute with a value >= 0 to it.
1 | <!DOCTYPE HTML> |
Any input class="focusTrigger"
are focusable elements we install our pseudo-class listener on. Initially we set any focusPopup
to invisible by defining their max-width / max-height
as zero.
The CSS rule .focusTrigger:focus + .focusPopup
describes the direct follower element (sibling) of the focusTrigger
in case the button has received the user input focus (mouse click). So when the pseudo-class becomes true, this rule changes the max-width / max-height
properties of the focusPopup
to make it visible.
Additionally we do not want to close the focusPopup
when it receives a click, because its focusTrigger
would lose the :focus pseudo-class then. So I also defined a rule that does the same as .focusTrigger:focus + .focusPopup
, but becomes true on mouse-hovering the focusPopup
. This results in the CSS alternative .focusTrigger:focus + .focusPopup, .focusPopup:hover
.
I used max-width / max-height
instead of width / height
to avoid a fixed size for the focusPopup
. I haven't tested this on all browsers, but this seems to make the content take its "preferred size". Originally this menu was created as slide-menu, being fixed on browser viewport, hovering the page content. When using this as push-menu, you could also use display: none;
and display: block;
instead of max-width / max-height
. But mind that the display
can not be animated by e.g. transition: 1s;
, animation you could achieve only with some size-property.
Mind that this solution won't work when the focusPopup
is not the direct follower of focusTrigger
!
:target
TabsThis example shows how tabs can be implemented without JavaScript. But mind that clicking on an internal link
Further you can not make the first tab initially visible.
So you may find this solution to be not so useful. Anyway, here is the example.
1 | <!DOCTYPE HTML> |
There are three hyperlinks on the page. Each points to a different internal target HTML-id: a href="#linkedTab1"
. The target itself is the tab, given as element with that HTML-id. All of them are initially invisible by the rule .linkedTab
.
When the user clicks on a hyperlink, the CSS pseudo-class :target
becomes active on the target element (which is the tab). Then the rule .linkedTab:target
applies and sets the tab visible. The rule .linkedTab:target
is stronger than .linkedTab
because it has a higher specifity.
Pure CSS solutions are not really user-friendly. CSS is more for colors, fonts, borders, and maybe also for layout. Building menus or tabs on CSS always leaks somehow (which does not mean that we shouldn't use pseudo-classes).
ɔ⃝ Fritz Ritzberger, 2015-12-19