Determine if any CSS rule directly modified an element's style - javascript

Suppose I have
HTML
<foo>
<bar>
<baz>Hello!</baz>
</bar>
</foo>
CSS
foo {
color: red;
}
bar {
color: red;
}
How can I take an element and determine whether its color style attribute was the result of matching a direct CSS rule or by inheritance?
// foo -> true - the first CSS rule directly applied a color to this element.
// bar -> true - the second CSS rule directly applied a color to this element. It didn't change the color that would have been inherited, but that's ok.
// baz -> false - The color in this element is purely inherited.
function isColorSetDirectly(DOMElement) {
...?
}
Using JS, I:
Can determine the effective color of text (Hello!) in a tag (baz) using getComputedStyle.
Can tell if a style was applied directly with HTML using the style attribute by checking element.style.color.
Can't tell if the rule that determined the style was directly applied to the element or if the element inherited the rule.
If CSS rules could be exhaustively enumerated, I could use element.matches/matchesSelector for every CSS rule that defines color. But since CSS rules can be set anywhere (external stylesheet, inline style tag, element style attribute, etc.) it seems difficult to enumerate all CSS rules that could affect an element.
The code initially loaded with the page (HTML/CSS) can't be changed but may be freely manipulated with JS.
Bonus
Is there a way to find out which element baz is inheriting its color from?

You can use window.document.styleSheets[i].rules to get CSS rules. You can get the selectorText, style, or the full cssText. For info on how to use this: https://stackoverflow.com/a/27527462/804495
All stylesheets, regardless of if it was included via <link> or <style> will be in window.document.styleSheets. However, this will not get element style.
To resolve this, you can use getComputedStyle on an element as you mentioned. If an element has a style declaration that is not in any of the styleSheets, then you know it is an inline style= CSS rule, either applied directly or through its ancestor chain.
Is there a way to find out which element baz is inheriting its color from?
It's possible. To find out which element it is inherited from, you will have to iterate through the parent elements; however based on the way CSS declarations work this should be exhaustive.

Use browser developer tools. Most modern browser has developer tools to help you debug CSS, javascript, network problems. Press F12 to start in Chrome, firefox (firebug plugin) and IE.
http://developer.chrome.com/devtools
http://msdn.microsoft.com/en-us/library/dd565628(v=vs.85).aspx

Related

Javascript/AngularJS: Check if an element has the style overflow-y applied to it

I am trying to check inside my code if a has applied to its css styling the attribute overflow-y: auto. For example if my has a class "abcd", and "abcd" has for its css overflow-y: auto, then the passes. While I've already found a method for jquery, which I am not using, I want to find a method for pure javascript (or Angular JS) to find if the element has a given css attribute. How can I do this without jquery?
You can check with pure javascript by using this code : document.getElementById('myElement').style['overflow-y'].
The issue is that this code will works only for inline css style, as in <div style="overflow-y: visible">...</div>. If the css style comes from a class, you can't find it like this.
The jQuery css method will find the computed style (so it can detect the real value of overflow-y even if it comes from a class). But the css code is very huge. You can find it here : https://github.com/jquery/jquery/blob/master/src/css.js
I want to add that checking if an element has a specific css style is a very bad smell.
Instead of this, you should really consider to check if the element has a specific class. Or if you have using angularjs, a simple boolean in the model will do the trick.
If you really want to check if an element has the overflow-y: auto; style applied, according to the jQuery code, they use window.getComputedStyle(element). They also have a lot of code with a temporary div with a weird position (position:absolute;left:-11111px;width:60px;) but it is mostly to support old browsers like IE8 and IE9.
In your case, something like this could works : window.getComputedStyle(document.getElementById('myElement'))['overflow-y'] === 'auto'.
You can use the getComputedStyle method available on the window object.
var myElement = document.getElementById('myElement');
var overflowValue = getComputedStyle(MyElement).overflowY;
if (overflowValue == 'auto') {
// your code here
}
This method will get values of css properties applied in the moment.
For more info, you can refer here.
hope that helps.

which HTML tags "support" background-color

How can I get/produce a list of all HTML elements (tagNames) for which background-color is meaningful (that is has an effect) ?
For example DIV should be in the list but LINK should not.
(I need this to optimize a chrome extension that goes over the entire DOM and calculate new background color values)
UPDATE
After much discussion of what the specific behaviour actually is, I think it has been demonstrated that any element (inlcuding made-up ones) will can have the background set, just as it says in the spec.
So, perhaps your chrome extension should check to see if elements have display: none, height: 0, or width: 0 and exclude them from your list by these criteria. That is, exclude elements that are being hidden from displaying in the viewport.
According to the spec, all elements can have a background and background-color. However, some elements are not allowed inside a <body> and so should not ever be displayed on a web page. I don't know which of these (or why!) simply do not render a background or color, but these can be skipped by your extension.
<base>
<link>
<meta>
<noscript>
<script>
<style>
<template>
<title>
There may be more elements that are not generally displayed, but these are from the Metadata section of the HTML5 spec.
The specification said all elements. But you have to think if it make sense or not :)
https://www.w3.org/TR/CSS2/colors.html#background-properties
Value: <color> | transparent | inherit
Initial: transparent
Applies to: all elements
Inherited: no
Percentages: N/A
Media: visual
Computed value: as specified

After a background color change with Javascript the :hover don't change the color

I have a long form with many fields. Some of the fields get their data from separate DIV, where there are other more specific fields.
Every field, along with its label, is included into a separate block. To highlight the fields there is a CSS :hover for their class.
The CSS :hoveron the fields blocks works smoothly, and also the onmouseover and onmouseout over the many DIV passing data to them, using the following Javascript:
function LineOn(whichOne) {
document.getElementById(whichOne).style.backgroundColor = '#cf0';
}
function LineOff(whichOne) {
document.getElementById(whichOne).style.backgroundColor = '#fff';
}
But, after the execution of the Javascript, the hover stops to work (i.e. the block remains white), without reporting any console error or message.
This happens both with Firefox 36.0.3 and with Chrome 39.0.2171.71, running on a Slackware current release.
Is there a sort of hierarchy giving to the background color set with Javascript the priority over the one defined in the <style> section?
Yes, styles defined directly in the element's style property overrides any value set in CSS, unless that style has !important on it.
CSS specificity http://www.w3.org/wiki/CSS/Training/Priority_level_of_selector
The priority level of the selector is decided in Point of combination of selectors.
style attribute = a
number of ID attributes in the selector = b
number of other attributes and pseudo-classes in the selector = c
number of element names and pseudo-elements in the selector = d
That's one good reason not to set styles attributes; set a CSS class instead yet.

Difference between body.style.backgroundColor and window.getComputedStyle(body).getPropertyValue('background-color')

I am trying to get the background color of the body, and I am wondering what is the difference between:
body.style.backgrounColor and
window.getComputedStyle(body).getPropertyValue('background-color')
Given that var body = document.getElementsByTagName("body")[0];
Is there any other way I can get the background-color?
Using:
document.body.style.backgroundColor
sets the style directly on an element, or returns the current value of the related style property that has been set through the style attribute or property. Such values are considered by a user agent when determining how to display an element when applying CSS rules (if there are any).
An element's style object does not necessarily reflect values applied to an element through CSS rules, though they may be the same (by chance or deliberately setting both to the same value).
The order in which style rules are applied to an element are listed in the CSS2.1 spec. Rules applied directly to the element are of second highest precedence, after !important declarations.
Using:
window.getComputedStyle(document.body, null).getPropertyValue('background-color')
is described in the DOM Level 2 specification. Basically, it returns the current style property values being used to display an element based on CSS rules, i.e. what is actually being applied to the element.
This often different to the value of the related style property (which not have a value unless set by a property or attribute).
Actually, document.body.style.backgroundColor will get only inline style property of an element like this
<body style="background-color:red">
On the other hand window.getComputedStyle will get the actual property after CSS and styles are applied to the element, for example, this is possible to get using window.getComputedStyle
body{
background-color:#fff;
}
But it's not possible to read css style given above using document.body.style.backgroundColor. Check this example. Also, check this.
just using body.style.backgroundColor will only be able to sense if an inline style is on the body and give you that (e.g. a style applied via the style attribute in the html or using the style property in JavaScript). getComputedStyle also gets styles that were applied to it via stylesheets in <style> tags, inherited styles from parent elements, and everything.
In short, body.style.backgroundColor will get the background color that was in the style attribute (<body style="background-color:red>) or applied through JavaScript, getComputedStyle will also be able to get style from stylesheets (<style>body{background-color:red}</style>)
If you have
background-color: red !important;
anywhere in your .css files, or <style> elements, that will override inline style e.g. style="background-color: blue;"

Quickly repaint array of unicode symbols in JavaScript

I want to change background/foreground color of many symbols with the same CSS class. Right now I'm doing it with jQuery — like $('back_COLORED').css('background-color', '#00FF00'), but this approach is slow when there are many elements with such class (>900).
Seems it's because jQuery don't change CSS rules itself, but finds all elements one-by-one and applies inline styles to them. At least, this is what I see in inspector. So, the question is:
How can I change the CSS rules itself?
Will it be much faster?
Can I make it cross-browser (IE6 doesn't count)?
UPD: I'm trying to make some kind of color scheme editor. The source is at http://github.com/kurokikaze/cinnabar/. Don't mind PHP things, editor is fully client-side (with just some libraries fetched from the net).
UPD2: Tried canvas approach, still slow. Canvas branch is at http://github.com/kurokikaze/cinnabar/tree/canvas.
The most cross-browser friendly way to override a class definition is to write a new rule and add it to the end of the last stylesheet in the document. You can edit an existing style rule, but even some recent browsers can make it difficult.
function newRule(selector, csstext){
var SS= document.styleSheets, S= SS[SS.length-1];
// this example assumes at least one style or link element
if(S.rules){
S.addRule(selector,csstext,S.rules.length);
}
else if(S.cssRules){
S.insertRule(selector+'{'+csstext+'}'),S.cssRules.length)
}
}
newRule('.someclass','background-color:#0f0');
You can add as many 'property:value;' bits in the csstext as you need.
Remember to prefix a '.' to a class name or a '#' to an id,
and the css must be written as a style rule (with-hyphens, not camelCase).
Of course, it will not override inline styles, and it is overkill for small, local changes.
It also may make the redrawing of the page more obvious than changing one element at a time,
but it may be just what you need here.
There are different ways depending on which browser you are dealing with. This is documented on Quirks Mode.
Some libraries provide an abstraction layer, such as YUI's StyleSheet utility.
There should be a significant performance boost since you aren't using JS/DOM to cycle through all the elements.
Another approach would be to predefine your styles:
body.foo .myElements { … }
And then edit document.body.className
If you can select the parent div by id, maybe you could select by tag inside it? Or are there elements of the same kind that should change color and that should not, inside the parent?
It would be nice to have an idea of what you're building here. 900+ objects seems to be a lot... maybe a completely different approach could be used? Canvas, SVG?
Try hiding the items you want to change before changing them, make the change and then display them again. This is common practice to speed up things as you minimize the repaint events in the viewport. In this case when you only setting one css property it might not be that of a benefit but it´s worth a try I say.
Try:
$('back_COLORED').hide();
$('back_COLORED').css('background-color', '#00FF00');
$('back_COLORED').show();
or
$('back_COLORED').hide().css('background-color', '#00FF00').show();
I would stick in trying changing a CSS property, instead of parsing the DOM.It is about the CSS engine vs. DOM+JS here, and the winner is clear.
It happens I just uploaded a tiny library that replaces CSS by Javascript: jstyle
This is may be an overkill, but you will find in the source code of jstyle.js all the code you need to update cross browser the CSS properties of your page.
I think a better solution would be to write a more specific CSS rule (that would override the normal colour) that can be activated by simply changing one element's css class.
So for example if you had the following structural markup:
<div id="container">
<span class="colored">Test 1</span>
<span class="colored">Test 2</span>
</div>
And CSS:-
.colored { background-color: red; }
.newcolor .colored { background-color: blue; }
Then in your jquery you add the .newcolor class to the container div:-
$('#container').addClass('.newcolor');
When you do that the second CSS rule will override the first because it is more specific.
Inject the css code into a style tag:
var style = $('style').attr({
type:"text/css",
media:"screen",
id:'changeStyle'
}).html('.tempClass { color:red } .tempClass p { background:blue }').prependTo('body');
and on every changes on your color with color picker you only rewrite the html inside of #changeStyle tag.
Have no idea if it works (didn't tested) but you should give a try.
This is jQuery pluggin for work with css rules: http://flesler.blogspot.com/2007/11/jqueryrule.html
not sure about its performance, but worth a try.

Categories

Resources