style.setProperty does not render - javascript

It seems like using this function would be more portable or reliable, because the alternative is to set an attribute:
element.style.setProperty(styleproperty, valuestring);
element.setAttribute('style',styleproperty+': '+valuestring+';');
The second method would also seem slightly more inefficient though that's hardly a concern.
But at least on Chrome, the style does not update on the page unless I use the setAttribute method.
The reason why this is a bit of an issue, is that I have potentially many different separate style properties I want to modify independently of the others. I have to do a whole lot of string parsing and processing if I can't make use of setProperty, removeProperty, etc. I have to pull out the style string, search it, modify it, and set it back in via setAttribute. Should work, but I don't like it.
Is there a reason for this? Is this a bug? My guess is that setAttribute triggers something for the browser to perform a re-render. What is a suitable way to force this update that is generally browser-friendly?

Setting the style attribute directly has consequences that may be undesirable: it will wipe out all existing styles set in the element's style attribute, and setAttribute is broken in older IE (and compatibility modes in later IE). Much safer is to use the element's style property directly to set only the style property you need:
element.style[styleproperty] = valuestring;
This will update the page immediately in all major browsers.
One caveat: CSS style properties (generally using dashes, such as in background-color) do not map precisely to properties of the DOM element's style object (generally camel case, such as in backgroundColor). There are also exceptions to this rule.

Related

Browser doesn't update when changing CSSStyleRule with JS

It seems like when modifying the CSS properties of elements when using JS methods (CSSStyleSheet, with insertRule or deleteRule, or CSSStyleRule.style.setProperty()), the underlying CSS has been updated, but the page itself not not reflect the changes.
The changes are only realised upon some reflow trigger, say after I've changed the attribute of the element, even if it's an invalid one.
May be related to this question: What are the conditions under which a browser will re-assess and reapply CSS selectors and styles?
What is the recommended way to modify CSS using JS? Apart from changing class strings, or a hacky way to insert and delete attributes?
Note: Testing on Edge / Chromium
After reading your post, I'm not sure if you are aware of these simple ones:
element.style = stylestring (IE: "display:block; color:red;")
or
element.setAttribute('style', stylestring)
These will be treated as inline-styles. So changed properties will take priority over the external css and the effect will be immediate.
Now, is it the recommended way? That's a tough one, I'll let others answer this question, I'm not really a W3C guy...

element.style or window.getComputedStyle() does not showing float

I am trying to copy all element style properties, to another element. (both inline and inheritance)
to do so I am using window.getComputedStyle(), but when I am taking all the style values the float value does not exist.
I even tried to use element.style and it not exist there.
but when I am using jQuery.css('float') I am getting the right value back, so it's exists for sure!
do you have any solution or smart way to do it?
Two things to consider: window.getComputedStyle() does not work in IE < 9 (docs here). Also, when accessing the float value via element.style, the property is named cssFloat because 'float' is a reserved word in JS (docs here). In IE < 9, the property is named styleFloat.
The reason your example works via jQuery is because jQuery knows of the inherent browser differences when reading calculated styles, and smoothes over them so that you can access them via a consistent API.
element.style maps to the style attribute, which does not consider inherited/external styles. For old IE, the property you want is element.currentStyle, which takes the inherited styles into account.
If you need a solution that does not rely on jQuery, you'll need to check for window.getComputedStyle() and use it if present, and fall-back to element.currentStyle for old IE (using the property styleFloat).
Hope that helps, cheers!

jQuery .css() returning pixels instead of percent

Alright, so when I get a CSS property that's been stored as a percent using jQuery .css() it is returned with its pixel value. This is great for my purposes actually, I can use it...is it an intended result I will see consistently in all modern browsers both now and in the future, though?
I can't seem to find much info here. Thanks!
Yes, you can see this behaviour in all browsers both now and in future. Because this is how browsers render the css property. Scripting languages will get these details from the DOM after it got interpreted from the browser. So this is the natural behaviour and this wont change.
Additionally, Percentages will be converted into pixels based on the element's parent during rendering process. So that it will not display the css property in percentage while you retrieving that. You have to calculate it manually if you need it for sure.
From jQuery doc
The .css() method is a convenient way to get a style property from the first matched element, especially in light of the different ways browsers access most of those properties (the getComputedStyle() method in standards-based browsers versus the currentStyle and runtimeStyle properties in Internet Explorer) and the different terms browsers use for certain properties.
yes it is an intended result
if you want to find the actual style value , you can do something like this,
var topValue = $("#mydiv")[0].style.top
This is covered by the burgeoning CSSOM specification. In general, yes, you can rely on pixel values provided the display property is not set to none. Section 9 of the above has the details; for most properties where you'd expect a number (width and such), it says:
If the property applies to the element or pseudo-element and the resolved value of the 'display' property is not 'none', the resolved value is the used value. Otherwise the resolved value is the computed value.
...where "resolved value" means (for these properties) a number of pixels rather than a relative amount (percentage and similar), which would be the "computed value" ("computed" as in "taking all style rules into consideration").
Supporting the case of this being (newly) specified behavior, when non-pixel values have been returned in various situations, bugs have been reported and accepted (in WebKit, in jQuery, in YUI).

Overriding containers CSS behavior

I have created a Javascript based element that can be embedded into websites. The Javascript itself adds the HTML code into a pre-defined HTML container and dynamically loads the necessary CSS file that contain the element's visual definitions.
The problem starts when the site itself has its own definitions for general items. For example: The site's CSS defines a certain list style which is applied on the element's list because the element's CSS doesn't define an explicit list style or if the site's CSS overrides the element's CSS definition.
For the time being, I was able to solve this specific issue by explicitly defining the list's style and adding the !important definition. However, I would definitely want to go for a more robust solution that will assure that:
1. CSS definitions from the site's CSS that are not explicitly defined in the element's CSS will not be applied on the element
2. I will not need to explicitly add the !important definition to every one of my CSS definitions
Is there a general way in which I can specify that a site's CSS will not be applied on a certain element or that only a certain CSS will be applied to a specific element?
Any help will be greatly appreciated.
You need to use a localised reset.
Grab an existing CSS reset, such as Eric Meyer's Reset Reloaded and namespace all the selectors with your parent element, e.g. #something a { ... }.
I was going to put up the same answer as Alex, but he beat me - but I was also going to add:
If you're not going to use #alex's suggestion then ultimately you have to explicitly style all of your elements the way that you want them to appear; using selectors that keep your styles local too (and don't interfere with the parent site) - in the same way that the localised reset is suggested.
Update
Or you could do what Google Translate and many other widget-type things do, usually a no-no but in dynamic scenarios I think perfectly acceptable; since the visual style of your elements is not just important to you but to the container site: use inline styles.
Final update
So I thought I'd just double check what Google Translate does. And of course it's an iFrame inject in addition to using inline styles. They no doubt use inline styles to maximise compatibility and so that the browser doesn't have to make another request to get the stylesheet; and they would be using an iFrame so they can ensure a consistent look and feel.
Consider both of those points in tandem - and weigh that up against the amount of work that might be required in resettting all the styles for a minority portion of the page; or defining rules for every CSS property you need to control - which, let's face it, is basically all visual CSS properties.
The iFrame solution actually seems to offer the best solution - if you can use it; hence I've +1'd the first comment by #roberkules on your question.

Javascript/Jquery: .css pixel-values

I just realised there is a difference between
<foo>.css('marginTop')
(which I thought is the standard jquery-notation) and
<foo>.css('margin-top')
(which I thought was non-standard).
If has margin-top: 3em; (for example), the first notation gives me 3em, the second notation gives me 48px (which is 3em in Pixels).
I like this behaviour but I could not find anything about it in the API (or am I blind?)
Why is this the case and where can I find information about it?
P.S.: Just to be precise: of course other attributes but margin-top work aswell...
Thank you!
The doc says “jQuery can equally interpret the CSS and DOM formatting of multiple-word properties”, but in reality it is doing that through rough and ready hacks which don't always behave predictably.
In particular, if you supply a DOM-style camelCaseName, it will first try to access the inline style declaration as style.camelCaseName. Then if that fails (typically because the style was not set inline), it falls back to trying getComputedStyle with the camelCaseName converted to hyphen-separated-name(*). The computed style is not the same thing as the declared style: the browser can resolve various relative declarations in a computed style, such as converting lengths to pixel units.
However, the reverse does not hold! If you supply a CSS-style hyphen-separated-name, it jumps straight to the computed style(*) code without trying to convert to camelCaseName and look at the inline style.
I don't think I'd want to rely on this behaviour... it smells a little bit buggy to me. If you can keep the inline style declaration off the element you want to measure, you should be able to ensure you always get the computed style back regardless of which name type you use. But then again, jQuery doesn't give you that as a documented promise. Such is the nature of trying to hide a complicated model behind a seemingly-simple “Do What I Mean” interface.
(*): except in IE where there is no getComputedStyle function, so it falls back to a weird and fragile mix of currentStyle, runtimeStyle and document alteration to try to get a computed style out.
The difference is related to CSS and JavaScript notation of the same thing. It would not be in the jQuery API but in a CSS reference.
CSS uses the margin-top while JavaScript uses the marginTop for the same thing. The default value in CSS (margin-top) is 0px. Therefore you get the 48px instead of the 3em.
See http://www.w3schools.com/css/css_reference.asp for more info.

Categories

Resources