I'm wondering how fallbacks work in CSS. For example:
background-image: url("images/icons-page1/getq.png");
background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE3LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjM0LjIzNHB4IiBoZWlnaHQ9IjMxLjg2NnB4IiB2aWV3Qm94PSIwIDAgMzQuMjM0IDMxLjg2NiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMzQuMjM0IDMxLjg2NiIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxzeW1ib2wgIGlkPSJBcnJvd18zIiB2aWV3Qm94PSItMTEuNTkyIC0xMC43NjQgMjMuMTg0IDIxLjUyOCI+Cgk8Zz4KCQk8Zz4KCQkJPGc+CgkJCQk8cG9seWdvbiBmaWxsPSIjRkZGRkZGIiBwb2ludHM9Ii0xMS41OTIsLTEwLjc2NCAtMi42NzEsMCAtMTEuNTkyLDEwLjc2NSAxMS41OTIsMCAJCQkJIi8+CgkJCTwvZz4KCQk8L2c+CgkJPGc+CgkJCTxnPgoJCQkJPHBvbHlnb24gZmlsbD0iI0VGRUZFRiIgcG9pbnRzPSItMTEuNTkyLC0xMC43NjQgLTIuNjcxLDAgLTExLjU5MiwxMC43NjUgMTEuNTkyLDAgCQkJCSIvPgoJCQk8L2c+CgkJPC9nPgoJPC9nPgo8L3N5bWJvbD4KPGcgaWQ9IkxheWVyXzEiPgo8L2c+CjxnIGlkPSJMYXllcl8yIj4KCQoJCTx1c2UgeGxpbms6aHJlZj0iI0Fycm93XzMiICB3aWR0aD0iMjMuMTg0IiBoZWlnaHQ9IjIxLjUyOCIgaWQ9IlhNTElEXzlfIiB4PSItMTEuNTkyIiB5PSItMTAuNzY0IiB0cmFuc2Zvcm09Im1hdHJpeCgxLjQ3NjYgMCAwIC0xLjQ3NjYgMTcuMTE3MSAxNS44OTU0KSIgb3ZlcmZsb3c9InZpc2libGUiLz4KPC9nPgo8L3N2Zz4=");`
First image is given with location. Second image is provided with value of the svg. I think it's clear that the second one will be displayed if browser supports svg, otherwise the first one.
What I'm wondering is, the first one is loaded and then the second one also loaded, since the second one modifies value of background-image finally it persist. if second one is not working for some browsers, then first one persist.
In both cases browser tries to load both of their value right? Or only the last one is executed?
I'm asking for performance related answer.
There is probably no explicit statement about this in specifications, but actual browser behavior (which can be observed by monitoring the network traffic for simple test documents) is that a URL is processed and accessed only after the browser has decided, applying the cascade rules, that a property value with url(...) is actually used. Thus, if a rule contains two background declarations that are syntactically valid as per CSS syntax, only the latter is used.
In the example case, the first background declaration never has any effect. It would be a different matter if the second declaration were of different syntactic form, say a keyword like dwim, which might be defined in some CSS spec in the future. Then old browsers would ignore it and use the first declaration instead.
So there is no fallback. The browser decides, on the basis of syntax (parsing) and by the cascade, which declared value will be used for a property, such as a url(...) value for background. If it then turns out that URL does not work or yields an image in an unsupported format, the browser does not go back and try another declaration instead.
Related
I have been reading this article about HTML5 Custom Element.
It said I need to register the element's name before using it like:
var XFoo = document.registerElement('x-foo');
document.body.appendChild(new XFoo());
Then I can start using it normally:
<x-foo>...</x-foo>
But I just tried using it without registering in Chrome, Firefox, and IE11. All seems to render just fine, even CSS selector for x-foo also works.
I'm guessing that we no longer need to register since most browsers have supported it?
Thanks
Short answer: No.
As a good practice, always define things that are not official. Just because it works by all/most browsers does not make it correct. That would be similar to using a variable which is yet to be defined, and then the compiler automatically defining it. Sure, it works, but that does not make it right
No, and document.registerElement isn’t even supported widely. It is experimental technology, work in progress.
Browsers traditionally treat unknown element names as specifying elements that have generic properties of HTML elements but no default functionality and no default rendering (the content is rendered according to its own rules). However, old versions of IE ignore an unknown element name in CSS unless you introduce it with code like
<script>document.createElement('x-foo')</script>
Using registerElement is useless for such purposes, since it is not supported by IE.
If you use registerElement, you should take caution, since calling it causes an error and script termination in many browsers. So you would need code like
if('registerElement' in document) {
var XFoo = document.registerElement('x-foo');
...
}
I'm currently using google chrome to inspect the elements of a bigger project I am working on and noticed that it gives very neat hints (e.g. striking through properties that are later overwritten). It also gives the hint that a property is invalid with a yellow exclamation mark. Is this information browser specific and it is only not valid in google chrome or can I assume that this property will not work anywhere? (of course I could look up every property for which I get this warning, but if I knew definetely these were unnecessary I could get rid of them without much hassle)
Striking through properties that are overwritten should generally reflect general CSS rules, i.e. be browser-independent. But the browser’s code for that might be buggy. Moreover, a potentially overriding rule might use a nonstandard value for a property, and then it would depend on browser whether it really overrides.
Indicating properties as “invalid” in browser tools should be taken just as saying that the browser does not recognize (support) the property. So it would be very much browser-dependent. It may also depend on browser version.
I'm not sure this is possible, but id like to set all user styles back to chrome defaults for div and descendants.
I'm building a Chrome plugin that creates a popup on any web page, however due to the fact every page has a plethora of custom styles, trying to track down every inconsistency and overwrite it with my divs (and descendants) custom style, it is becoming a nightmare.
Every time I think I've covered all bases another site implements something else that needs to be overridden.
What would be the easiest approach to standardize my popup in this situation?
One approach I can think of is to (bite the bullet) and get a hold of the the default Chrome CSS styles and implement them into a series of catch all descendant selectors, however surely there is a better way.
If you want to be absolutely sure that the styling of your elements is not affected by the web-page's CSS, there are 2 possible solutions:
Use an iframe to implement your popup. (This solution is "safe" and simple enough, but based on the kind of interaction between the popup and the web-page it might become cumbersome.)
Utilize the Shadow DOM. (This is probably the "proper" solution, but the implementation might be a little more complicated.)
Some resources regarding the 2nd solution:
An introductory tutorial.
An actual example of incorporating the "Shadow DOM" concept into a Chrome extension:
RobW's Display Anchors extension
There is a third option worth discussing and rejecting, which is to reset all the style properties of the div and its descendents to its default value. Pseudo-code:
#my-div, #my-div * {
#for-every-css-property {
%propertyName: initial !important;
}
}
This answer shows an attempt at such a solution. It uses specific values instead of initial which will work in older browsers without the initial keyword, but will not correctly reset elements which have a different default from the base (e.g. user566245 mentions that textarea elements should have a border).
Issues:
Unfortunately initial is not actually the browser's default value.
If we don't use !important above then there is a risk that the page might have provided a rule with a more specific elector which overrides our own. For example if the page specified properties for table > tr > td then this would be applied over our rule because that selector is more specific than #my-div *.
Since we do use !important, any custom styling we want to do after the reset must also use !important on every property.
If the page happens to inject any additional CSS styles after ours that uses !important then these can override our reset.
It is rather inefficient. We are asking the browser to apply a huge bunch of CSS rules to every element under our div.
Vendor-specific properties should also be reset. (E.g. -webkit-animation-name.)
If new CSS properties come into existence in future, you will need to update your list.
Whilst this solution can be applied to current browsers, it is rather horrible, so roll on Shadow DOM! I would recommend the <iframe> solution in the meantime.
I don't know if anyone has tried this, but a more efficient solution might be to use Javascript to detect what site-defined CSS properties could be problematic, and reset only those.
When using the same CSS property in one rule set, in the case of needing to provide a fallback for browsers that don't support a property you may be using, like so:
body{
background: rgb(255, 255, 255);
background: rgba(255, 255 ,255, 0.5);
}
Do browsers that understand both of these declarations render the first, then overwrite it with the second? Or does a browser save itself the hassle and only render the latter?
Edit: I am aware that if a browser understands both declarations it will render the latter, but I want to know if the browser renders/draws the first into the viewport and then overwrites it with the second or does a browser work in a way that means it only renders the one declaration that is required, potentially saving itself resources?
I would expect modern (and probably old) browsers to parse the CSS rules supplied to it before rendering anything. Here's a screenshot from the Chrome profiler for both rules:
And here's another, for only the first rule:
As you can see, there are no extra steps involved when two different rules are present. If the browser was to render it twice, you would see another "Paint". (The slight reduction in paint time for the single rule is likely to be because I removed the rgba rule, so the browser did not have to take transparency into account).
the last of the 2 will be applied
To be more precise: the first will be applied, then the second.
It would be the same as having 2 identical selectors setting the background property.
The one most descriptive will be applied. If they are the same, the last declared will be the one applied.
The "C" in CSS stands for Cascading which means styles can add to or supercede preceding CSS rules. So the second declaration will override the first.
Browser handle this correctly. You can use that kind of rules.
For example, chrome will apply rgba, and IE8 will apply rgb.
Browsers in general apply the following algorithm:
for each element in the DOM tree
for each CSS rule
if rule's selector matches element
apply all declarations in rule
render
This is not how it works:
for each CSS rule
for each element in DOM tree
if rule's selector matches element
for each declaration in rule
apply declaration
render
That would be a huge performance problem.
It follows from the basic UA conformance requirements that browsers must first parse all CSS rules, then decide, by the principles set in the specifications, what values shall be used for each property of each element. There is no allowance for “incremental rendering” in the sense of applying part of the CSS code before reading the rest. And it would be very odd for a browser to deviate from this, as it would mean more work to implementors, more complaints from authors and end users, and no benefits.
After looking through everything except the Gecko source, I'm somewhat confused by the following behavior. I wanted to see if I could style a text input based on a user-inputted value, and eventually ended up with this CSS:
input[value="password"] {
border:1px solid red;
}
The problem is, it seems the value of an input is only checked on the elements creation, as seen in this example.
Is it possible to accomplish this without the use of Javascript? Why would a browser not update styles accordingly?
It doesn’t work, because attribute selectors “match elements which have certain attributes defined in the source document” (Attribute selectors in CSS 2.1). Things are a bit more complicated really, because calling setAttribute('value','password') on the input element causes a match in many browsers (not IE). But this is irrelevant if you don’t use JavaScript.
There is, however, an indirect way, though it is mostly theoretical for the time being, due to limited browser support and to complications in implementations. You could write:
<style>
input:valid { border: 1px solid red; }
</style>
<input pattern=password id=x>
This uses the HTML5 pattern attribute, in this case specifying a regular expression that is merely a fixed string with no wildcards, and the CSS3 Basic UI :valid pseudo-class that tests whether the element’s state satisfies validity constraints. This is not suitable for normal use (e.g., no support in IE 9), but in special situations in controlled environments, things like this might be usable.
However, browsers that support such features tend to have their own reporting of validity errors, like special color around the box when the value is invalid, and I don’t think you can change that in CSS – JavaScript might help, but… So the reporting might conflict with your goals here. Moreover, it seems that browsers supporting these features treat the element’s state as valid when the box is empty. This is odd, and attempts to work around this my making the input obligatory (HTML5 attribute required) seem to open new cans of worms rather than fix. But maybe in some cases you could use just some initial value, say value="?", that the user is expected to replace by this input.
No. CSS cannot check the value of an input field past what is available in the HTML structure.
When you're typing into an input field, you're not actually changing the attribute in the HTML.
This does not work because you're not actually changing the value attribute of the element. For example, look at this fiddle:
http://jsfiddle.net/jblasco/J9xSd/
It does work, because the value attribute is actually changed. Simply typing in the field, or updating it through the Javascript method you used, does not change it. Which is normally useful, for getting the default value later, but perhaps not-so-useful in this sense.