Is there a way do determine if a selector is currently been applied to an given element?
I know it´s possible to iterate over all CSS selectors, and test if each one is applicably or not. But I´m not sure if this is the way that Firebug and other inspector do it.
EDIT:
I need a way to do it dynamically, with JS.
You can check if an element instance is matched by a selector by using document.querySelectorAll and Array.prototype.indexOf:
function elementMatchesSelector(element, selector) {
return Array.prototype.indexOf.call(document.querySelectorAll(selector), element) > -1;
}
Of course this only works for modern browsers that support the aforementioned methods.
Alternatively you can use Element.matches:
function elementMatchesSelector(element, selector) {
var fn;
if (!element) {
return false;
}
fn = element.matches || element.mozMatchesSelector || element.msMatchesSelector || element.webkitMatchesSelector;
if (fn) {
return fn.call(element, selector);
}
return false;
}
In Firebug, you can look at the Computed Side Panel. For any given DOM element, it shows the CSS styles applied (even those applied via JavaScript). It also depicts the styles that were overridden. From the docs:
The Computed Side Panel shows all CSS style values calculated by the user agent while interpreting the given CSS information for the selected node inside the HTML Panel.
What about using getComputedStyle()
MDN Link
Related
Is there a convenient way to check if an HTMLElement is an offsetParent?
I have a situation where I need to determine an element's offsetParent before it is inserted in the DOM. I can access the element's immediate parent, before insertion.
There doesn't seem to be any properties on HTMLElements that indicate whether or not it is an offsetParent.
Is there a good way to do this?
There is to my knowledge unfortunately nothing in the DOM API that does expose this information on the Element itself.
According to specs, an ancestor can be an offsetParent if
The element is a containing block of absolutely-positioned descendants
This means that not only positioned elements will qualify, but any element with a transform, or a filter property, a will-change with a value containing any of the aforementioned ones will also do.
However this behavior was not always specified this way, so it may return false positives in some browsers.
Also, it may be that in the future other CSS properties will affect what makes a containing block, or even in the present since I only got these from the tip of my head...
With that in mind, the surest is to append a test element inside your element and to check its offsetParent.
However, this will create forced reflows, so use it sporadically.
document.querySelectorAll('.container > div')
.forEach(elem => {
elem.textContent = isOffsetParent(elem) ? 'offsetParent' : 'not offsetParent';
});
function isOffsetParent(elem) {
const test = document.createElement('span');
elem.appendChild(test);
const result = test.offsetParent === elem;
elem.removeChild(test);
return result;
}
<div class="container">
<div class="is-offset-parent" style="position:relative"></div>
<div class="can-be-offset-parent" style="transform:translate(0)"></div>
<div class="can-be-offset-parent" style="filter:blur(1px)"></div>
<div class="is-not"></div>
</div>
But if you really wish some unsafe way which may need to be updated, then you could check all the properties I mentioned before using getComputedStyle(elem).
How can I create a new element using just a selector? (e.g. .myclass, #myid or a:not(.someclass)) Basically there is no way for you to tell if the element is a div, span, li, an anchor, if it's a div with a class or with an id and so on.
In jQuery I know you can do $(selector) to get a usable DOM object. But how can this be done in JavaScript?
In jQuery I know you can do $(selector) to get a usable DOM object...
Not to create one. jQuery will do a search in the DOM for existing matches. You can do $("<div>") and such (note that's HTML, not a CSS selector) to create elements, but jQuery doesn't have a feature for creating elements from CSS selectors.
But how can this be done in JavaScript?
You'll have to parse the selector, and then use document.createElement with the tag name, and then set any classes or other things the selector describes on the new element.
CSS selectors aren't very hard to parse. You'll be able to find a lib that does it. (jQuery has Sizzle, which is a selector engine, built in and Sizzle is open source. It will naturally have code to parse selectors.)
Mootools does this.
new Element('#name.class')
yields
<div id="name" class="class"></div>
The answer appears to be that there is no built-in way of doing this. Maybe there’s a library which does the job.
However, it’s not to hard to write a function to create an element from a simple selector:
/* createElementFromSelector(selector)
================================================
Usage: element#id.class#attribute=value
================================================ */
function createElementFromSelector(selector) {
var pattern = /^(.*?)(?:#(.*?))?(?:\.(.*?))?(?:#(.*?)(?:=(.*?))?)?$/;
var matches = selector.match(pattern);
var element = document.createElement(matches[1]||'div');
if(matches[2]) element.id = matches[2];
if(matches[3]) element.className = matches[3];
if(matches[4]) element.setAttribute(matches[4],matches[5]||'');
return element;
}
var testitems = [
'div#id.class#attribute=value',
'div#id.class#attribute',
'div',
'div#id',
'div.class',
'#id',
'.class',
'#id.class',
'#whatever'
];
testitems.forEach(item => {
var element = createElementFromSelector(item);
console.log(element);
});
The tricky part is the regular expression. You can see it in detail here: https://regex101.com/r/ASREb0/1 .
The function only accepts selectors in the form element#id.class#attribute=value with the any of components being optional, as you see in the test items. I think including pseudo classes is probably pushing the friendship, but you might like to modify it to include multiple real classes.
I want to change the style of visible elements using CSS only. Is there a selector that does it? It needs to work with Chrome and Firefox only. (I am building an extension / addon)
If there isn't, is there a way to change the style of visible elements with a light javascript?
Visible within the current scroll position. An element can be out of the scroll vision, or partially visible.
There is no standard pure CSS rule for assessing visibility.
As others have said, jQuery (if you wanted to use jQuery) has both a CSS selector extension :visible and the ability to execute .is(':visible') on any given jQuery object to get the computed style on any given DOM element with .css("display") or .css("visibility").
It's not particularly simple in plain javascript to determine if an object is visible because you have to get the computedStyle (to take into account all possible CSS rules that might be affecting the element) and you have to make sure no parent objects are hidden causing the child element to be hidden. This is a function I have in my own personal library:
//----------------------------------------------------------------------------------------------------------------------------------
// JF.isVisible function
//
// Determines if the passed in object is visible (not visibility:hidden, not display: none
// and all parents are visible too.
//
// Source: http://snipplr.com/view/7215/javascript-dom-element-visibility-checker/
//----------------------------------------------------------------------------------------------------------------------------------
JF.isVisible = function(obj)
{
var style;
if (obj == document) return true;
if (!obj) return false;
if (!obj.parentNode) return false;
if (obj.style) {
if (obj.style.display == 'none') return false;
if (obj.style.visibility == 'hidden') return false;
}
//Try the computed style in a standard way
if (window.getComputedStyle) {
style = window.getComputedStyle(obj, "")
if (style.display == 'none') return false;
if (style.visibility == 'hidden') return false;
} else {
//Or get the computed style using IE's silly proprietary way
style = obj.currentStyle;
if (style) {
if (style['display'] == 'none') return false;
if (style['visibility'] == 'hidden') return false;
}
}
return JF.isVisible(obj.parentNode);
};
There is no pure CSS way of doing this. As Kirean's comment already said, why would you want to style visible elements only? Invisible elements won't show their styling anyway. If you don't want the invisible element to take up space (aka, laid out), you should use display: none;
If you REALLY want a selector to select the visible elements, you could do what Widor suggested and use jQuery. You could first use jQuery to first select the visible elements, add a class to them, then use CSS to select the elements by that class.
$('div:visible').addClass('visibleElement');
.visibleElement {
color: red;
}
There is no Way to select invisible elements, using pure CSS
http://www.w3.org/TR/selectors/
However, if you have a class name or other selector, using jquery you can do something like the following
jQuery(selector).each(function(){
Var $this=$(this);
if ($this.css('visibility')==='hidden')
//set your style
})
Edit: after your edit, there is definitely no way of selecting what is within the viewport with CSS alone. It is a context free language of sorts.
However, you can always fool around with an elements offset position with jquery and determine if it's within the current viewport(window.scrollposition or something similar). This type of solution gets messy quickly, though.
This looks like a :visible selector to me:
http://api.jquery.com/visible-selector/
EDIT: Saw your javascript tag before your 'no CSS' caveat.
But this is a CSS selector of sorts.
In jQuery, we can easily get the CSS value for a given element with the css method:
$('#myElement').css('line-height'); // e.g. '16px'
Now, since this CSS value might have been inherited from a parent element, is there any way to know which element has this rule applied to it?
For example, let's say I have the following HTML:
<div class="parent">
<div id="myElement"></div>
</div>
and the following CSS:
.parent {
line-height: 20px;
}
Calling the css method on #myElement will return 20px, but it will not indicate that it was inherited from .parent.
I know I can just fire up Web Inspector/Dev Tools/Firebug, but I want to get it programmatically.
Is this at all possible?
Walk up the parentElement chain checking the css() value of each element. The first element with a parent().css() value that's different is (probably) the element being targeted by the CSS rule selector.
See this fiddle for an example: http://jsfiddle.net/broofa/VPWV9/2/ (See the console.log output)
(Note: there are almost surely complex cases where this won't work as expected but for the case as described, it works.)
I have a similar solution to broofa's. It also has the same problem though.
Here's the fiddle:
http://jsfiddle.net/2w3kt/
$.fn.getStyleParent = function(property)
{
var $source = this.get(0), // only do for 1st element :P
srcVal = $source.css(property),
$element = null;
$(this).parents().each(function()
{
var $this = $(this);
if( $this.css(property) == srcVal )
element = $this;
else
return false; // stops the loop
});
return $element;
}
This is not to be confused with "How to tell if a DOM element is visible?"
I want to determine if a given DOM element is visible on the page.
E.g. if the element is a child of a parent which has display:none; set, then it won't be visible.
(This has nothing to do with whether the element is in the viewport or not)
I could iterate through each parent of the element, checking the display style, but I'd like to know if there is a more direct way?
From a quick test in Firefox, it looks like the size and position properties (clientWidth, offsetTop etc.) all return 0 when an element is hidden by a parent being display:none.
Using Prototype:
if($('someDiv').visible) {...}
As I'm using MochiKit, what I came up with based on Ant P's answer was:
getElementPosition('mydiv').y != 0
I can also check whether it's in the viewport (vertically) by:
y = getElementPosition('mydiv').y
(y < getViewportPosition().y + getViewportDimensions().h &&
getViewportPosition().y < y)
Incidentally this also works in IE6.
Relying on the position being 0 is brittle. You're better off writing a helper function to iterate through the parents to check their display style directly.
Here's the iterative solution -
var elementShown = function(e){
if (e == document)
return true;
if ($(e).css('display') == 'none') //or whatever your css function is
return false;
return elementShown(e.parentNode);
}
.getClientRects() will return an empty array if the element is not displayed by inheritance (display="none" from parent/ancestor element)