css style not loaded when window.onload is triggered - javascript

Here is my problem : the css style is not initialised when window.onload is triggered.
<div id="foo"></div>
css file
#foo {
height: 200px
}
js file
window.onload = function(){
console.log(document.getElementById('foo').style.height);
};
the console displays : ""
the style must be in a different file, if the style attribute is used (style="height=200px") it works.

.style.height does not show styles that come from CSS rules. It only returns styles that have been explicitly set on that object, either in the HTML or via javascript, not styles inherited from CSS rules.
Instead, you must use window.getComputedStyle(). See the MDN doc for more details on how to use getComputedStyle() properly. Here's one example:
window.getComputedStyle(document.getElementById('foo'),null).getPropertyValue("height");
Note: for older versions of IE, you have to either install a polyfill for getComputedStyle or use el.currentStyle.

Element.style will only be set for inline styles(<div id="foo" style="height: 200px"></div>), to get the computed style use window.getComputedStyle
window.getComputedStyle(document.getElementById("foo"), null).getPropertyValue('height')

You can also consider working with jquery, a very popular javascript libraray with tons of very nice and powerfull features. And if you use the google cdn you don't need to worry about performance cause most browsers will already have the libray in cache.
To get the height of an element you would just use .height() The full explanation is here http://api.jquery.com/height/
Your code would look something like this:
$(document).ready(function() {
console.log($('#foo).height());
});
It may look a bit confusing at first, but you will quickly get the hang of it, and you will be writing js a lot faster and more compact with jquery. I never go without it!

What you really want is either offsetHeight or clientHeight. Try this:
window.onload = function(){
console.log(document.getElementById('foo').offsetHeight);
};

Related

Replacing in-line div style

I'm trying to replace the in-line styling of a div using Dojo. I only want to change the min-height property, without affecting any other in-line properties.
Here is my current HTML:
<div id="divid" class="divclass" style="width: 950px; min-height: 225px;">
Here is my script string:
dojo.query('div.divclass').css( "min-height", "0px" );
But it seems to have no effect at all. If I try to swap the .css() for .attr() it works fine except it removes the other styling - .attr('style', 'min-height:0px');
Manually editing the div code is not an option so I'm looking for a workaround. I also tried appending another class but the in-line styling overwrites it.
I got the .css() part from a jQuery site so maybe it's not compatible with Dojo? Sorry I'm pretty new to this.
Thanks
There is an alternative for Dojo as well (compared to jQuery), however, the function is called style() in stead of css(), for example:
dojo.query('div.divclass').style( "min-height", "0px" );
Also, this functionality is not available by default, you also need to load the module dojo/NodeList-dom, because it contains extra DOM functionalities for the NodeList (which is the list of nodes you get when you use the dojo/query module).
Another small thing to notice: be sure that the DOM is loaded before you're going to query it, if the DOM isn't loaded yet, there's nothing to query either.
A full example (using AMD) would be:
require([ "dojo/query", "dojo/NodeList-dom", "dojo/domReady!" ], function(query) {
query('div.divclass').style( "min-height", "0px" );
});
The dojo/domReady! module is similar to $(document).ready() in jQuery, it makes sure that the DOM is loaded before you query it.
The working example can also be found on JSFiddle: http://jsfiddle.net/Eu9Br/

use a javascript variable in inline CSS

I want to do the following:
<div id="theDiv" style="width: aJavascriptVariableOrFunctionCallToGetValue">TESING</div>
I don't want to use, elsewhere in the code,
document.getElementById('theDiv').style.width = someValue;
I actually want that div, when it first appears, to have a width set, inline, by either a JavaScript variable or by way of a call to a JavaScript function.
How can I do this?
This is impossible to do the way you see this.
Every time the variable changes, you need to update the style of that particular object:
var theDiv = document.getElementById("theDiv");
document.getElementById('theDiv').style.width = someValue;
I really don't understand what you mean that when it first appears you want it's width to be set to certain width - why do you want to do that inline? Why can't you just set the width in your Javascript? What's preventing you from doing that? Especially if you want to do it just once and don't want to change it dynamically.
If you want to link the width of the div to a variable, look at frameworks like Backbone or EmberJS. You can then define a renderer that changes the width when the variable changes.
The only way to get JavaScript to run when an element first appears is with an onload event handler. And onload events only work on a few specific elements, like body, script or img.
Here is how you could make it work in your case, with a img tag:
<div id="theDiv">
TESING
<img style="display:none;" src="tinyImage.jpg" onload="this.parentNode.style.width='100px';"/>
</div>
Honestly, I don't see this as a good practice, and I would recommend to just be patient, and set the width later in a script.
Live demo: http://jsfiddle.net/HKW6b/
You cannot do it like that. There are other ways to achieve what you want, though.
Server side processing, specially if the technology you use supports templating. You can manipulate the html value before sending it to the client;
jQuery may be something to consider. Simply fetch the element and use its API. Example:
$("#theDiv").width(aJavascriptVariableOrFunctionCallToGetValue);
This small piece of code does exactly what you want. It is not written inside the element itself, and it is about equivalent to the sample you provided, but again, it's something to consider should you have to do more complex operations on the DOM later on.
If you want to execute that piece of code only once, and after the page is ready, you can do it like this:
var div = $("#theDiv");
div.ready(function () {
div.width(aJavascriptVariableOrFunctionCallToGetValue);
});
The solution for this issue allowed me to set the proper width of the div immediately, asymptotically approaching inlined-javascript as possible, as per one of the comments above suggested:
"If you need the style applied immediately, you can embed a script immediately following your HTML markup and then you won't have the flash of unstyled content I'm guessing you want to avoid. – Harvey A. Ramer"
This solved the 'slow server' => FOUC problem. I added a 'script' tag immediately after the div tag to set the div to the window.innerWidth, problem solved.
From what I've seen, this approach is the earliest/soonest/fastest way to use javascript to set a CSS style attribute -- and it avoids having to code up an 'onload' handler.
The problem with 'onload' handlers being used to set UI style attributes on the page is -- the onload Javascript handler function can grow...and grow...and grow over time over the project's lifespan and you eventually are forced to clean out the onload handler. Best approach is to never use an onload handler that sets styles in the first place.
I'm using React, and this syntax worked for me:
<div id="theDiv" style={`width: ${aJavascriptVariable} %`}>TESING'</div>

which one is given more preference for JavaScript or CSS?

here is my code
<!doctype html>
<html>
<head>
<style>
body {
color:red;
}
</style>
<script>
window.onclick = function(){
document.getElementsByTagName("body").color="blue";
}
</script>
</head>
<body>
here is some text for test
</body>
when i run it in my browser (initially it is red) and click in window it doesn't respond to click i mean it should change the color of text from red to blue but nothing happens. Where am i wrong?
Try this:-
Demo
This will add style attribute to the body element, which will override the css rule.
window.onclick = function(){
document.getElementsByTagName("body")[0].style.color="blue";
}
It should be style.color as color is a property of style property of element and even though it is body .getElementsByTagName returns a collection so you need to use document.getElementsByTagName("body")[0] to get the element and apply style to it.
And yes styles applied the element direclty will override the class css rule
Style property has more precedence over styles applied by class.
document.getElementsByTagName("body").color="blue";
This has more preference
Also color is a property of style attribute.
So your style should have looked something like this as getElementsByTagName returns a node list.
document.getElementsByTagName("body")[0].style.color="blue";
it is a better idea to use classes instead, cause it is lot cleaner.
Inline CSS is more powerful and overrides CSS defined anywhere else.As far as working of your code, I modified it a little bit like this:
window.onclick = function(){
//document.getElementsByTagName("body").color="blue";
document.body.style.color="blue";
}
DEMO here
You have an error in your JS. getElementsByTagName returns a NodeList (which is like an array), not a single element. You need to set the property on an element, not a NodeList. For example:
document.body.color="blue";
Setting the color property of the body element (IIRC, it's been a very long time since I went near that part of HTML) is equivalent to setting the color attribute. This is an obsolete presentational hint attribute.
The CSS specification says:
The UA may choose to honor presentational attributes in an HTML source document. If so, these attributes are translated to the corresponding CSS rules with specificity equal to 0, and are treated as if they were inserted at the start of the author style sheet. They may therefore be overridden by subsequent style sheet rules. In a transition phase, this policy will make it easier for stylistic attributes to coexist with style sheets.
So the style specified in the stylesheet should continue to apply.
On the other hand, setting a style.something property is equivalent to modifying the style attribute on an element.
document.body.style.color="blue";
In the cascade, !important declarations aside, properties set via the style attribute are most specific.
So of those two rules, the blue one would win.
JS inserts the changes inline, giving them pretty much the highest priority, unless you have !important in your css.
Check to see if you code (document.getElementsByTagName("body").color="blue";) works from the dev console (F12 for Chrome). There appears to be a problem with it. I can't help debug, however, as I usually do such actions via jQuery, and vanilla JS color changes are unintuitive for me.
js and css does not compete with each other, what you are doing is essentially javascript applying css to an html element, this means that its still css, that type of css is called inline css, . As others have said inline css has more precendence over normal css except if you use !important in your css rules
As to why your code is not working, because you are doing it wrong.
Change
document.getElementsByTagName("body").color="blue";
To
document.getElementsByTagName("body")[0].style.color = 'blue';
Here's a jsFiddle
http://jsfiddle.net/n2kqd/

How can I change cssText in IE?

In the past I've been able to modify the CSS on a page via an inline style tag.
I know this sounds horrible but it's for custom CSS writing while working on a kind of WYSIWYG (not with text though).
I used to do something like:
tag.styleSheet.cssText = myrules;
I don't know when exactly, but at some point IE started saying "Invalid Argument" when I try this. The real crux is that doing tag.innerHTML = 'body {}' gives Unable to set value of the property 'innerHTML': object is null or undefined which doesn't happen in any other browser.
EDIT
To be clear I am using an inline style tag. I am not trying to use the inline style attribute.
<style type="text/css" id="mytag"></style>
How can I change the inside of that tag?
EDIT 2
Please see this fiddle:
http://jsfiddle.net/tTr5d/
It appears that my solution of tag.styleSheet.cssText is identical to using styleSheets property. You can comment out the last definition of cssText to see it working as proposed by #Teemu. So now I'm real lost why it's not working in my app. If anyone has ideas what could break that functionality that would be great. In the meantime I'll be tinkering around my app.
IE is limited to 32 stylesheets. I like to forget that fact apparently, which seems to include inline style tags, on top of <link>.
I changed my sandbox to turn on minification so it would put the files together.
Then my code worked.
So it appears that when you go over the limit and insert via JS, you don't get a real error until you try what I did.
You can get a reference to a styleSheet object only via styleSheets collection (or imports collection). If you refer direct to the style element, you'll just get a HTML-element. (Check properties in both objects within simple for..in-loop, and see the difference)
This works in all IEs, and results are rendered immediately:
document.styleSheets['mytag'].addRule('BODY', 'background-color:red');
More info in MSDN: styleSheet object
You can use jQuery. If it's the inline style, you can use the .attr() function.
$("#myElement").attr('style')
otherwise, you can see what .css() has to offer. You can use that to get and set various CSS styles.
Other CSS related jQuery methods
I never had much luck with style elements and IE's innerHTML.
The dom methods are surer, even if you need to branch for IE;
without jquery-
function addNewStyle(str, title){
var el= document.createElement('style');
if(title) el.title= title;
if(el.styleSheet) el.styleSheet.cssText= str;
else el.appendChild(document.createTextNode(str));
document.getElementsByTagName('head')[0].appendChild(el);
return el;
}

Can !important rules be used in IE's CSS expressions?

Firstly, I know that CSS expressions are defunct and wrong in so many ways, and also to avoid using !important where possible. This is for a special case stylesheet.
In Short
My question is... Is there any way for a CSS expression to set the !important flag?
E.g. this doesn't work:
a { color:expression('red !important'); }
[Edit: thanks to MarmaladeToday's comment below]. This also doesn't work:
a { color:expression('red') !important; }
Can this be done some other way?
In Detail
What I'm actually trying to do is mimic the inherit value in IE6 & 7. This works:
color:expression(
this.parentNode.currentStyle ?
this.parentNode.currentStyle.color: 'red'
);
But I also want to set the !important flag, and this doesn't work:
color:expression(
(
this.parentNode.currentStyle ?
this.parentNode.currentStyle.color: 'red'
) + ' !important');
I'm aware that, in JavaScript, it isn't possible to set !important via an element's style object. E.g. this won't work:
element.style.color = 'red !important';
However, it is possible to set !important via the element's style attribute:
element.setAttribute('style', 'color:red !important;');
So... are CSS expressions limited to interacting with the style object, and therefore, what I want to achieve is impossible - or is there any way for an expression to affect an element's attributes, or pass !important in some other way?
Starting a Bounty
No solid answers so far, so I'm starting a bounty.
Ideally, I'm looking for a CSS-based solution for mimicking inherit !important in IE6 and IE7, either with or without CSS expressions. (Please do verify that your suggestions work before posting).
At least, a link to some authoritative reference telling me that this is impossible would mean I could lay this train of thought to rest - I've not seen anything mentioning the use of CSS expressions with the !important rule.
The reason those CSS expressions don't work is because IE only evaluates the expression for the last property in the cascade.
E.g. if you have an HTML document with a link inside it and the following "CSS",
a {
color: expression(function(e){
alert('success');
e.runtimeStyle.color = 'blue';
}(this));
}
a { color: red; }
you will never see that alert (nevermind the style change), because the CSS expression is never evaluated. So no, you can't use an expression to set the !important flag.
That is to say, not when you try to set it on the same property. You can cheat. But that does make the expression a bit more complicated:
a {
filter: expression(function(e){
e.runtimeStyle.color = 'blue';
alert('success');
e.style.filter = '';
}(this));
}
a { color: red; }
There are a few things to note here.
If you simply use another CSS property, you can be sure that the expression will be evaluated. Or at least, a little more sure, because if there's another rule further down the cascade that uses the same property already, you're still out of luck.
Secondly, you have to use runtimeStyle instead of currentStyle. If you used currentStyle here, the second rule would still end up overwriting it. runtimeStyle overrides all other CSS (except !important declarations). So it's the JScript equivalent of !important.
Also note that I'm resetting the filter property itself as well. That prevents the expression from being continuously re-evaluated. But as much as that may reduce performance, I don't think it's super critical. The main reason I put it in here is because I added alert()s in those expressions, and you definitely don't want to have those pop up forever.
It is in fact also possible to use any other property you make up. This works too:
a {
bogus: expression(function(e){
e.runtimeStyle.color = 'blue';
}(this));
}
However, since the bogus property doesn't actually exist, you can't reset it using Javascript, so this will be re-evaluated continuously.
color:expression('red') !important;
You could try the behavior property, it's a lot more versatile than expressions.
Try this,
inherit.htc :
<SCRIPT language="JScript">
//add your own inheritance logic here, you can use element.parentNode etc.
var prop = element.currentStyle.behaviorProp;//specified in stylesheet
var val = element.currentStyle.behaviorValue;//specified in stylesheet
element.style[prop] = val;//set as inline style, you can also use setAttribute here.
</SCRIPT>
css:
body #div1 {
color:blue;
}
#div1 {
color:red;/*stays blue, because 'body #div1' is more specific*/
behaviorProp:color;/*specify styleproperty for the .htc*/
behaviorValue:green;/*WILL become green, because the .htc sets it as an inline style, which has priority.*/
behavior:url(inherit.htc);
}
This sounds sick and evil, but:
color: expression((function (_this) {
window.setTimeout(function () {
_this.setAttribute("style", "color:" +
(_this.parentNode.currentStyle ?
_this.parentNode.currentStyle.color : 'red') + " !important";
}, 0);
return _this.parentNode.currentStyle ?
_this.parentNode.currentStyle.color : 'red';
})(this));
In other words, this:
Returns "red" (or the parent color) immediately.
Sets a timeout that will set "red !important" (or whatever) immediately after.
Keep in mind that this could end up hosing your browser though. I didn't test it, and stuff involving CSS expressions tends to go terribly wrong.
The venerable ppk of quirksmode has done some work on CSS, JavaScript and the !important keyword. (Note that for test in Firefox or any other non-IE browsers, use cssRules instead of rules below.
Here's the link: W3C DOM Compatibility
You can apparently read whether a style rule in a stylesheet is important by doing this (this would get the importance level of the color property in the 2nd css rule in the 2nd stylesheet, IN ALL BROWSERS EXCEPT MICROSOFT INTERNET EXPLORER. How's that for a bummer.
document.styleSheets[1].rules[1].style.getPropertyPriority('color')
//Returns important when the style is marked !important.
//Returns an empty string otherwise.
Now, his research reveals yet another way to set !important, unfortunately this also apparently only works in non-Internet Explorer browsers
// where x is a DOM element
x.style.setProperty('color','#00cc00','!important');
// Set the color of x or the second rule in the second style sheet to green.
document.styleSheets[1].rules[1].style.setProperty('color','#00cc00','!important');
Apparently this strange syntax, if you are not setting things as !important, requires setting the third parameter to null:
// where x is a DOM element
x.style.setProperty('color','#00cc00',null);
// Set the color of x or the second rule in the second style sheet to green.
document.styleSheets[1].rules[1].style.setProperty('color','#00cc00',null);
Now, MSDN has a property called "cssText" that dangles off the style object of a DOM element. It even indicates that CSS expressions are okay. The usage is:
x.style.cssText = 'color: #00cc00 !important';
Now, this may be important (heh), the MSDN page says (emphasis mine):
DHTML expressions can be used in place of the preceding value(s). As
of Internet Explorer 8, expressions
are not supported in IE8 mode. For
more information, see About Dynamic
Properties.
It may be worthwhile to check out ppk's tests of cssText as well.
I unfortunately don't have the relevant versions of Windows Microsoft Internet Explorer available on this laptop, but perhaps this is of some use. I'm curious to how this shakes out, it's something I'd run into (setting !important in JavaScript) but found other ways to get around it, typically just shifting around classes or applying specificity by using an ID in the relevant selectors.
Best of luck on an interesting question!
It's been my understanding that !important is largely these days as a hack... specifically because IE does NOT recognize it.

Categories

Resources