Let us begin by acknowledging that:
- HTML is primarily for structure
- CSS mainly deals with presentation
- JS focuses on behavior
Note: The discussion of whether presentation that responds to user interaction is essentially another term for behavior is open to interpretation. One perspective holds this view.
However, the myriad interactive visual effects seen across the web created solely in CSS and triggered by
:hover
,:focus
,:focus-within
, and other pseudo-class states suggests a different widely accepted viewpoint – that CSS is a valid technology for managing what could be termed as interactive presentation.
I'm curious (as I couldn't find any information) if, despite the numerous ways CSS is used for handling interactive visual presentation, it has ever been utilized for dealing with interactive aural presentation?
Have there been endeavors to incorporate aural presentation into CSS?
Is there a proposal to include aural presentation in CSS?
Is there any official strategy at all (even if not yet implemented by browsers) to achieve what the following demo accomplishes using these hypothetical CSS properties:
audio
audio-duration
audio-play
Working Example:
For now, let’s ignore the hastily written JavaScript below and imagine that CSS styles like these:
.square:unhover {
audio: url(//cdn.freesound.org/previews/628/628357_1486333-lq.mp3);
audio-duration: 1.776s;
audio-play: 2;
}
simply work as they are supposed to.
// BUILD STYLESHEET ARRAY
const stylesheet = document.head.querySelector('style');
let stylesheetText = stylesheet.textContent.replace(/\s/g, '');
let stylesheetArray = stylesheetText.split('}');
stylesheetArray.pop();
// BUILD SELECTORS ARRAY
let selectorsArray = [];
for (let i = 0; i < stylesheetArray.length; i++) {
selectorsArray[i] = {
selector: stylesheetArray[i].split('{')[0],
styles: {}
};
let selectorRules = stylesheetArray[i].split('{')[1].split(';')
selectorRules.pop();
for (let j = 0; j < selectorRules.length; j++) {
selectorsArray[i].styles[selectorRules[j].split(':')[0]] = selectorRules[j].split(':')[1];
}
}
// BUILD TARGET QUERIES ARRAY
let targetQueriesArray = [];
for (let i = 0; i < selectorsArray.length; i++) {
if ((/:hover|:unhover/).test(selectorsArray[i].selector)) {
if (Object.keys(selectorsArray[i].styles).includes('audio')) {
let targetQuery = selectorsArray[i];
switch (true) {
case (targetQuery.selector.includes(':hover')): targetQuery.event = 'mouseover'; break;
case (targetQuery.selector.includes(':unhover')): targetQuery.event = 'mouseout'; break;
}
targetQueriesArray.push(targetQuery);
}
}
}
// DECLARE playAudioViaCSS FUNCTION
const playAudioViaCSS = (audioURL, audioDuration, audioPlays) => {
let soundEffectViaCSS = new Audio(audioURL);
soundEffectViaCSS.loop = true;
soundEffectViaCSS.play();
setTimeout(() => soundEffectViaCSS.loop = false, (audioDuration * audioPlays));
}
// ATTACH AUDIO EVENTS TO TARGET ELEMENTS
for (let i = 0; i < targetQueriesArray.length; i++) {
let targetAudio = targetQueriesArray[i].styles.audio.replace('url(', '').replace(')', '');
let targetAudioDuration = (targetQueriesArray[i].styles['audio-duration'].replace('s', '') * 1000) || 1000;
let targetAudioPlays = targetQueriesArray[i].styles['audio-play'] || 1;
let targetEvent = targetQueriesArray[i].event;
let targetQuery = targetQueriesArray[i].selector.replace(/:hover|:unhover/g, '');
let targetElements = [...document.querySelectorAll(targetQuery)];
targetElements.forEach((element) => element.addEventListener(targetEvent, () => playAudioViaCSS(targetAudio, targetAudioDuration, targetAudioPlays), false));
};
:root {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
.square {
width: 100px;
height: 100px;
line-height: 100px;
text-align: center;
color: rgb(255, 255, 255);
background-color: rgb(255, 0, 0);
border-radius: 50%;
cursor: pointer;
transform: scale(1);
transition: all 0.9s ease-out;
}
.square:hover {
border-radius: 0;
transform: scale(1.5);
audio: url(//cdn.freesound.org/previews/354/354062_1490240-lq.mp3);
audio-duration: 2.304s;
audio-play: 3;
}
.square:unhover {
audio: url(//cdn.freesound.org/previews/628/628357_1486333-lq.mp3);
audio-duration: 1.776s;
audio-play: 2;
}
<div class="square">
Hover me
</div>