Why can only certain CSS styles be accessed from javascript? - javascript

Here's an example block of css:
p {
position: relative;
color: blue;
font-size: 100%;
top: 100px
}
Then if I include a paragraph tag which calls a javascript function upon being clicked:
<p onclick="logStyles(this)">Test</p>
Strangely, only some styles are accessible...
function logStyles(obj) {
console.log(obj.style.color);
console.log(obj.style.position);
console.log(obj.style.fontSize);
};
The element's color value shows up in the console and I am able to change it's value to say "blue" from my javascript. But the second two functions log nothing to the console and those style values are inaccessible.
red page.html:16
page.html:17
page.html:18
Why is this the case? I am running the latest version of Chrome.
The css and javascript files are included through links in the head as so:
<script src="js_methods.js"></script>
<link rel="stylesheet" type="text/css" href="stylesheet.css">

You're talking about the COMPUTED style. That's something different from the inline style.
See: How do I get a computed style?

By doing it this way you can only get the styles directly associated with the HTMLElement object. What you're looking for are the computed styles:
var styles = window.getComputedStyles(elem);
console.log(styles["color"]);
See mozilla

Related

Can I use scoped CSS while printing HTML page? (using Laravel and Vue.js)

Should I put the scoped CSS in my master file, or should I change the print function in order to accomodate components' scoped CSS? In the second case, how should I change the JS function?
I use Laravel 5 with many Vue Components. In one of them, I have the following scoped CSS
<style scoped>
td.not-purchased{
background-color: darkgrey;
}
td.not-assigned-here{
background-color: lightgreen;
}
td .checkbox{
margin-top: 0;
margin-bottom: 0;
display: inline-block;
}
table th:nth-child(n+3),
table td:nth-child(n+3){
width: 50px;
overflow-x: hidden;
text-overflow: ellipsis;
}
</style>
When printing the generated content, the function opens the content in a new page and copies the external CSS in the HEAD of the original document.
$(document).on('click', '.glyphicon[data-printselector]', function(){
if($(this).data('printselector') != ''){
// Print in new window
let printHtml = $($(this).data('printselector')).clone(),
printWindow = window.open(),
waitTimeout;
$(printWindow.document.body).append($('<div />', {class: 'container'}).append(printHtml));
$.each($('link'), function() {
$(printWindow.document.head).append($(this).clone());
clearTimeout(waitTimeout);
waitTimeout = setTimeout(function(){
// Here we ensure that CSS is loaded properly
printWindow.print();
printWindow.close();
}, window.changeFunctionTimeoutLong);
});
}
else
window.print();
});
I know this could be done by putting the scoped CSS directly into the master CSS of my website, but I believe this goes against the whole point of having scoped CSS.
The way Vue works by default, your scoped CSS is transformed in the following way:
The CSS selectors in your CSS get an additional attribute selector, and the CSS itself is inlined in a <style> tag into your page
The HTML elements matching the selectors in your CSS are given the corresponding unique attribute
That way, the CSS rules are scoped to the specific HTML elements that match the unique attributes.
If you want your scoped styles to work in a different context than the original page, there's two things you need to make sure work:
The HTML elements have the necessary attributes
The <style> tag with the CSS with those attributes is present
From your description, it sounds like the latter at least is missing. A quick thing to try this out would be to also copy all <style> tags from your page when you're copying the external CSS, and see if that works.
Then you can determine whether that's good enough for you, or whether you actually want to see about just grabbing the styles you need (in case you have a lot of styles).

Overriding CSS from element.style created by server side JS

I have a reference to a server side JS file that dynamically creates divs on my page. I am trying to override the css that is inline for the divs that are created but I have not been able to do so.
I have tried !important and the style that is created by the JS still trumps everything I do.
When i look at the style in the developer console of chrome it shows element.style as being the style that "won" over my style
I do not have access to edit the JS file on the server.
I place this in my page and it dynamically creates the divs and styles them.
<head>
<style>
#id
{
background-color: blue; !important;
display:block; !important;
}
.class
{
background-color: blue; !important;
}
</style>
</head>
<script src="http://xxx/xxx/xxxxx/xxxx.ashx?blank=xxxx" type="text/javascript" charset="utf-8"></script>
You can create your own javascript to restyle the divs created by the server javascript.
The CSS !important tag does sound like your answer here but sometimes you need to ensure your CSS declaration is specific enough to the element, i.e.:
<div>
<a style="color:#F00;">A Link</a>
</div>
If I apply the below CSS the inline style or #F00 will still win:
div {color:#fff !important;}
But if I am specific with my CSS declaration i.e:
div a {color:#000 !important;} <--Notice the 'a' tag
Then my link will be #000. This does not matter if the link was loaded in with JavaScript or not.
See my JSFiddle Example: http://jsfiddle.net/zqpy0r6c/
More technical info can be found at
When does CSS's !important declaration not work?
The CSS given in the style attribute on an element always wins over the stylesheets. The best option to override this CSS is to edit the style attribute using some JS:
<script>
function clearInlineStyling(element){
element.style= null;
}
</script>
Next you have to watch the html for your script to add new elements, find them and remove their styling. I would suggest JQuery for this.

Why does the javascript style property not work as expected?

<html>
<head>
<style type="text/css">
#wow{
border : 10px solid red;
width: 20px;
height: 20px;
}
</style>
</head>
<body>
<div id="wow"></div>
<script>
var val = document.getElementById("wow");
alert(val.style.length);
</script>
</body>
</html>
This is my code, why is val.style.length 0? Because I defined 3 properties, I expect it to be 3
An element's style property only reflects inline styles. It is essentially a way of getting (and indeed setting) inline styles.
From MDN:
[the style property] is not useful for learning about the element's style in general, since it represents only the CSS declarations set in the element's inline style attribute, not those that come from style rules elsewhere, such as style rules in the section, or external style sheets.
You can get all the styles applied to an element with window.getComputedStyle(element):
alert(window.getComputedStyle(val).length);
However, this probably won't do what you want, since it provides all the style properties on an element, even if they are still the default. In my browser (Chrome, FWIW), that means it always returns 285. This shouldn't be a surprise. The browser has a "built in" stylesheet that provides the defaults for all elements, after all.

Javascript - modify CSS on HTML tag?

The HTML tag on this page I'm working on is in a class that is giving it a top padding of 28px. I need this to go away temporarily when a button is clicked, but it doesn't appear that I can change the styling of the HTML tag itself.
Will I need to use position: relative; on the body tag or something similar? Is there really a way to assign CSS to the HTML tag that I don't know about?
# Comments:
Sorry, I'm in a bit of a rush here. It's something to the effect of this:
<html class='pad_my_top'>
<head>
<style type='text/css'>
.pad_my_top{
padding-top: 28px;
}
body{
background: #000000;
}
</style>
<script type='text/javascript'>
function its_gone(){
// Something here to remove padding.
alert("It's gone. Hurray!");
// Something to put it back.
}
</script>
</html>
<body>
<button onClick='its_gone()'>Click me to get rid of the top padding</button>
</body>
</html>
I really want it gone so I can print the page with Javascript, but I'd rather not use any 3rd party code because this is for a plugin for Wordpress and I don't want a billion dependencies. I only need to hide/re-display 3 divs and (re)change 2 styles.
Use this to remove the top padding:
document.documentElement.style.paddingTop = "0";
and this to set it back:
document.documentElement.style.paddingTop = "28px";
There's no reason to use getElementsByTagName and whatnot...just use document.documentElement. Also, it's better to use a class and toggle that instead of directly setting the style attribute. What if you change the 28px to 20px in your CSS? Then you have to change it somewhere else. Since you are sure you want the top-padding to be 0, then add a class that sets that. When done, remove that class. Like this:
<style type="text/css">
.no-top-padding {
padding: 0 !important;
}
</style>
document.documentElement.className += " no-top-padding";
And to "add" the padding back (by effectively removing the class):
var old_class = document.documentElement.className;
document.documentElement.className = old_class.replace(/(?:^|\s)no-top-padding(?!\S)/g, "");
Although it could be done a lot cleaner with the DOM API classList. The regex is just a safer way for making sure the className property is modified correctly to remove the "no-top-padding" class.

Applying css with javascript overrides hover link style?

I have some JavaScript which is changing an image correctly but once it has been called, my a:hover CSS code no longer works.
Looking with firebug the following JavaScript creates this css rule:
element.style {
background-image:url(/content/images/side_partnershipsOver.png);
}
document.getElementById('partnerships').style.backgroundImage = "url(/content/images/side_partnershipsOver.png)";
How can I apply the JavaScript and not have the a:hover code overriden by the element.style rule?
As far as I know setting the element.style.backgroundImage is essentially the same as using an inline style.
<style type="text/css">
a { background: blue; }
a:hover { background:green; }
</style>
<a href="#" style="background:red;">link<a>
Unfortunately the inline style always wins. In the above sample the link will always be red. As Daniel White said jQuery would be very useful here. Although you may be able to get around this issue in two ways.
One, Generate the style using javascript to write a style tag
document.write("<style type='text/css'>#partnerships { background-image:url(/content/images/side_partnershipsOver.png);}</style>");
or two, Manually setup mouseenter/mouseleave events to handle your hover style
Update
or three, as pointed out by KevinUK, use the !important css tag to override the inline style set.
<style type="text/css">
a { background: blue; }
a:hover { background:green !important; }
</style>
<a href="#" style="background:red;">link<a>
I was also frustrated about this CSS js style gap so I build
methods to apply style from js with a CSS string
elm.jCSS(cssText);elm.jCSSPseudo(cssText,pseudoElt)

Categories

Resources