Reputation: 10672
Is there any way that I can call a JavaScript
function via css?
For example, from this :hover
style:
.first-nav li a:hover,
.first-nav li.hover a {
margin:-3px 0 -1px;
height:30px;
position:relative;
background:url(../images/nav-hover.jpg) no-repeat;
}
The JavaScript
function I want to call is on an anchor :hover
.
Upvotes: 24
Views: 104013
Reputation: 81
Ok, so this can be done. I was looking for something similar (overloading the CSS attr() function to include JS formatting). While looking online I found this question, so I thought I'd add a way that it is possible.
For a start, if you can, you absolutely should use addEventListener, and hook the element up to the hover event. The solution I am about to provide is cheesy and not recommended.. .. .. ..but it does answer OPs question!
(useful links at the end)
Ok, onto the code. In CSS you can have custom properties, here's an example:
<head>
<style>
/* sets a custom property of "--my-text-color" with the value "red" */
:root {
--my-text-color : "red";
}
/* set paragraph text not by explicit declaration but by referring to the custom property */
p {
color: var(--my-text-color);
}
/* I can change the "--my-text-color" variable, however that scope is only for this node and its children */
p span {
--my-text-color:"green";
color: var(--my-text-color);
}
</style>
</head>
<body>
<p> some content
<span> more content </span>
</p>
</body>
If you've not seen custom properties before then it'll look odd, but essentially I created a variable called --my-text-color
at the :root {}
level, setting it to "red". I then use that value for the color
rule of <p>
using var(propertyName)
, however within that ruleset I also redefine the --my-text-color
property to "green", then use that to style the color
of text of the <span>
that is the child of the <p>
tag.
What this demonstrates is that you can change property values based on CSS rules, however what I didn't mention was that you can query that property value using script. For example, this bit of code..
console.log( window.getComputedStyle(document.querySelector("p")).getPropertyValue("--my-text-color") );
..then you would output "red", if however you to do this..
console.log( window.getComputedStyle(document.querySelector("p span")).getPropertyValue("--my-text-color") );
..you'd get green. Ok, so what does that achieve? Well it shows that you can change property values based on CSS rules, and that you can detect the value of those properties using JS.
Finally.. the answer! I know, lots of build up, but we're there now. As :hover is a CSS rule, and OP wants to run a JS upon hover, you can set up a JS loop that will monitor a rule, and run a script when it's changed, meanwhile you use the :hover pseudo-class to set that property. Thus, when hovered the property will change, and the JS will detect it.
I can't believe I've written all this for a 14 year old problem, with a solution that nobody should ever use, but it's been a fun experiment none the less. For some working code, try this..
<!DOCTYPE html>
<html lang="en">
<head>
<title>Test</title>
<style>
/* set property at root */
:root {
--foo: false;
}
/* some minor formatting */
.container,
.output {
padding: 2rem;
border: 1px dashed #888;
margin-bottom: 1rem;
}
/* upon hover, change the property to true */
.container:hover {
--foo: true;
}
</style>
<script>
// init the loop once the dom is in
document.addEventListener("DOMContentLoaded", checkProperty);
function checkProperty() {
// get the computed style sheet for the span element
const fooProperty = window.getComputedStyle(document.querySelector(".container")).getPropertyValue("--foo");
// const fooProperty will equal the "--foo" property set via CSS, the :hover altering its value
document.querySelector(".output").textContent = fooProperty;
// I am simply outputting the fooProperty value, instead I could run a function instead
window.requestAnimationFrame(checkProperty);
// this is just a simple loop, calling itself each anim frame
}
</script>
</head>
<body>
<div class="container">hover me</div>
<div class="output"></div>
</body>
</html>
If you paste that into an .html document, run it, you'll find hovering over the top div will change the text of the lower div. Instead of changing the text, I could equally run a javascript function.
Ok, so.. yeah.. it's certainly code I would never recommend, as there are far better and far easier ways to deal with a hover, but it answers OPs question even if it is somewhat cheesy.
The useful link bit...
Upvotes: 0
Reputation: 321
It's both an aesthetic quality and, as such, it should be handled with CSS and a functional quality which should, as such, be handled with html and javascript.
And there is a very simple way to call a function on page load from within html:
<body onload="myFunction()">
Upvotes: -1
Reputation: 22948
You can call it from javascript(it does the same thing). Below is the code on how to do it on JS:
<script type="text/javascript" src="http://code.jquery.com/jquery-1.4.2.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("a").hover(function(){
myFunctionInvoke();
});
});
</script>
or if you have particular anchor in mind just change the selector
Upvotes: 3
Reputation: 31
Actually. Yes you can. Just use javascript: in the background-url like this:
<STYLE type="text/css">BODY{background:url("javascript:yourFunction();")}</STYLE>
Not entirely sure if this will work though.
Cheers!
Upvotes: -2
Reputation: 338
Because it's more logical to do it from CSS.
If one wants to make links click on hover, it's an aesthetic quality and should be handled with CSS. For example:
#header_menu li a:hover{
color:white;
js:click();
}
Upvotes: -1
Reputation: 1075309
No, you can't trigger JavaScript from CSS directly.
What you can do is use CSS selectors to find the elements you want to watch in this way, and then watch for mouse events. The standard events are mouseover
and mouseout
, but they can be a bit tricky to work with because they bubble (you get mouseout
, for instance, whenever the mouse leaves any descendant element). With appropriate logic, though, they're not to bad to work with, and in fact if you have lots of these, you probably want to use mouseover
and mouseout
rather than the alternative below because you can set them on just a parent container and then work out which descendant element is involved, which can be simpler in some cases (and more complicated in others).
IE provides mouseenter
and mouseleave
which are much easier to work with because they don't bubble, but (of course) IE-specific. These are so handy that frameworks are starting to support them even in browsers that don't; Prototype and jQuery provide them, for instance, and I wouldn't be too surprised if some other frameworks do as well. jQuery also provides the handy hover
function, which would be very close to what you want:
// jQuery
$(".first-nav li a").hover(
function(event) {
// The mouse has entered the element, can reference the element via 'this'
},
function (event) {
// The mouse has left the element, can reference the element via 'this'
}
);
...which is really just a shortcut for setting up mouseenter
and mouseleave
handlers, but still, wonderfully concise.
In Prototype it's quite similar:
// Prototype
$$(".first-nav li a")
.invoke("observe", "mouseenter", function(event) {
// The mouse has entered the element, can reference the element via 'this'
})
.invoke("observe", "mouseleave", function(event) {
// The mouse has left the element, can reference the element via 'this'
});
(OT: In both cases, I've used anonymous inline function expressions just to avoid giving the impression you have to use named functions. I always recommend using named functions in production code, though.)
Upvotes: 28
Reputation: 944198
No.
(Well, Microsoft Expressions and Mozilla Bindings might allow it, but both are proprietary and should be avoided)
Assign your event handlers from JavaScript. Libraries such as YUI and jQuery allow you to pick elements to apply them to using CSS selectors. Event delegation allows you to handle events on elements without having to assign to each one explicitly (which is handy if you are adding them to the document after it loads).
Upvotes: 5