When using a CSS reset like
* {
all: unset;
}
inline SVG graphics are not shown correctly, see https://jsfiddle.net/593qysxp/1/
I have tested this with Safari 11 and Chrome 61.
I tried to solve this with setting the svg element to display: block or all: initialbut this did not help.
Does anyone has a solution?
If you want to leave SVG content completely alone and not reset anything inside them, you could use
#namespace svg "http://www.w3.org/2000/svg";
:not(svg|*) {
all: unset;
}
SVG 2 now defines a number of attributes as presentation attributes that were true XML attributes in SVG 1.1. Among them are cx, cy, rx, ry for <ellipse> elements and the d attribute for <path> elements.
That has the consequence that these, when written as attributes on the element, are treated as CSS properties. That is why they are overwritten by all: unset. (according to SVG 1.1 rules, see Addendum below.)
That means equally that they can be stated in a style attribute, where they would have a higher specicifity than any stylesheet.
As not all browser implement these presentation attributes yet, you would have to state them for now double as attributes and style properties. The result looks weird, if you ask me:
* {
all: unset;
}
head, link, meta, script, style, title {
display: none;
}
div {
display: block;
}
.icon {
width: 4rem;
}
<div>
<svg class="icon icon--search" viewBox="0 0 20 20"
version="1.1" xmlns="http://www.w3.org/2000/svg">
<ellipse cx="14.159" cy="5.87" rx="5.89" ry="5.849"
style="fill:none;stroke:#000000;stroke-width:1px;cx:14.159px;cy:5.87px;rx:5.89px;ry:5.849px"/>
<path d="M10,10l-9.98,10.02"
style="fill:none;stroke:#000000;stroke-width:1px;d:path('M10,10l-9.98,10.02')"/>
</svg>
</div>
The use of the path() functional notation is, by the way, still an open issue. So this may currently work, but not for long. This whole technique looks like something that I would not advise to use.
Addendum: Things get further complicated by a breaking change in the SVG spec I wasn't aware of until I just read up on it. SVG 1.1 has this to say about the CSS cascade:
The presentation attributes thus will participate in the CSS2 cascade as if they were replaced by corresponding CSS style rules placed at the start of the author style sheet with a specificity of zero.
SVG 2 instead says this:
Presentation attributes contribute to the author level of the cascade, following all other author-level style sheets, and have specificity 0.
First or last? So far I have not encountered any browser where presentation attributes supplant author style sheet rules. That includes this example. Following SVG 2 rules, your stylesheet rule should have been replaced by the attributes, but obviously weren't.
Related
I'm using inline <svg> for my icons on an html page. I have a component which renders a table, often with hundreds of rows. In this case, every row of the table has the same inlined svg. Usually they are simple icons with just a few paths, but it got me wondering if there is some way to optimise this. In this scenario inlining is important, I don't want to have references to any external files. Is there some way for me to have the inlined svg just once, and refer to that same element somewhere else? Is this something I should even be worried about? Is the overhead of repeating inline svgs minimal?
If you have hundreds of table rows with one SVG, they all are (SVG) DOM elements you have to duplicate/repeat. There is no equivalent to SVGs use in HTML (you could built that yourself with a Custom Element)
If performance really really is an issue you need to test if creating SVGs Server Side (SSR) performs better (in your use case) than creating SVGs Client-Side... but you're probably talking micro-seconds..
The Custom Element IconMeister (one of my pet projects) creates all used SVG icons Client side
(you can cherry pick from 7000+ icons)
Or if all your SVGs are 100% duplicates just a one liner with native JS cloneNode could be enough.
Or create a very simple IconMeister yourself in a W3C Standard Custom Element
for clean semantic HTML:
(100% supported in all modern Browsers, supported by all Frameworks... except React)
<style>
svg-icon svg {
--size: 120px;
width: var(--size);
height: var(--size);
}
[bg=blue] svg{
width:1px;
}
[bg=yellow] svg{
width:5px;
}
</style>
<h3>Who is afraid of Red, Yellow and Blue</h3>
<svg-icon bg="red" ></svg-icon>
<svg-icon bg="yellow" ></svg-icon>
<svg-icon bg="blue" ></svg-icon>
<script>
customElements.define( "svg-icon", class extends HTMLElement {
connectedCallback() {
this.innerHTML =
`<svg xmlns='http://www.w3.org/2000/svg'>` +
`<rect width='100%' height='100%' fill='${this.getAttribute("bg")}'/>` +
`</svg>`;
}});
</script>
I am trying to avoid having to <use class="myicon" xlink:href="myicon" /> by simply targeting the value of the xlink:href attribute when styling my SVGs. None of the following selectors seem to work:
[xlink|href*=myicon], // I also set the namespace at the top of the file
[xlink:href*=myicon],
[xlink\:href*=myicon] {
color: yellow !important;
}
A few other questions on the site seem to imply that styling using the attribute selectors on namespaced attributes should be possible, even though plain html has no support for namespaced attributes, as it should just regard them as one word. But I cannot get it to work, so I am losing faith in just that.
As Blake Mann says, if you're listing all your selectors together like that, it won't work because [xlink:href*=myicon] is invalid, which causes your entire ruleset to be dropped. If you're trying different selectors, you need to try them one at a time.
[xlink|href*=myicon] works just fine, but make sure you've specified the XLink namespace and not the SVG namespace:
#namespace xlink 'http://www.w3.org/1999/xlink';
html {
background-color: black;
}
[xlink|href*=myicon] {
fill: yellow;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<text id="myicon" y="16">Icon</text>
</defs>
<use xlink:href="#myicon" />
</svg>
You were definitely on the right track with what you were doing.. in fact, you have the right answer:
[xlink\:href*=myicon] {
color: yellow !important;
}
The reason it isn't working is because the first two selectors you tried were invalid (both the | and : characters need to be escaped), and if a CSS selector contains invalid characters, the whole selector group gets thrown out.
Check this example as proof... the div (just using a div for simplicity, even though that's not quite right) should get set to be red, as that rule comes after the blue one, but because the selector group gets thrown out, that rule won't get applied. The other selector that does not have the invalid characters will apply though!
[xlink\:href*=myicon] {
color: blue;
}
[xlink|href*=myicon],
[xlink:href*=myicon],
[xlink\:href*=myicon] {
color: red;
}
<div xlink:href="myicon">Lorem Ipsum</div>
My team are shifting to svg icons.
We use to define the icons in css style classes, and are now considering whether SVG icons should be implemented as view component rendering svg markup (instead of html). This should allow for better reuse svg by changing dimensions, color etc. On the other hand this takes the icons out of the styling domain and any style change will cause code change (and not only css change).
Whats is the right way (if there any) to work with svg icons, control size and colors, and still save style layer and view layer?
SVG editors sometimes put style information inline, but style information for SVGs can also be provided inside <style> tags, as usual CSS.
If the SVG is in your DOM (the simplest way to do this, is to write the SVG directly into your HTML) the SVG can be formatted directly from your usual CSS file:
p {
color: #666;
}
.blueTriangle {
fill: lightblue;
stroke: #666;
stroke-width: 8;
}
<p> This is usual text in HTML p tags. </p>
<p> The next thing is embedded SVG, styled by usual CSS: </p>
<svg width="250" height="120">
<path class="blueTriangle" d="M150 20 L130 90 L170 90 Z" />
</svg>
With transform also scaling and rotations can be done, showing different components can be accomplished via display, visibility or opacity with different implications.
Changing paths themselves would be considered as changing the content of the file and can be done via JavaScript. Therefore the separation of style an content can still be preserved.
What is the best, most maintainable and readable approach to setting a CSS property as the default for given tags in a portion of a page with low specificity. Currently, I have a page which takes the global default font styling from a html selector in a separate global stylesheet. There is a large portion of my page (which has the class dash) which I want to have a different default font style.
The main issue with just setting .dash h1 { font.... } is that this has very high specificity. Every time I want to set a font style for an element which is a descendant of .dash, I need to refer to .dash. Since I am working around a modular design, where each component is developed independently, this is a very bad idea. An even worse solution would be to set !important or to use an ID, for obvious reasons. Obviously, we don't run into this issue when setting fonts for html h1, or any other tag since all tags have lower specificity than classes.
Is there a simple low-specificity approach to setting a CSS property for tags which are descendants of an element high up in the DOM, selected by a class such that it can be overwritten by applying font properties to and element selected by another class?
You can set font properties with a rule like .dash { font ... } and set font properties for elements inside the element so styled, because each element gets it font properties from the declarations that apply to it, rather than its parent or other ascendant.
For example, if you have
<div class=dash>
some content
<h2>some heading</h2>
some content
</div>
and you set
.dash { font-family: Cambria }
then there is no problem in setting
h2 { font-family: Calibri }
without referring to the dash class. The h2 element gets its font family from the latter rule, quite independently of the rule that applies to its parent.
Doesn't
.dash * { font
do what you need?
UPDATE after clarifying comments and fiddles ...
So, I had your question "backwards" because I thought you were trying to ignore specifics in the included html.
BUT I think my suggestion still works, no?
.dash * { color: red; }
.included-class { color: blue /* this will take precedence */ }
http://jsfiddle.net/zDVED/
Based on Harry Roberts article http://csswizardry.com/2014/07/hacks-for-dealing-with-specificity/#safely-increasing-specificity, I applied the same class repeatedly in order to increase the specificity of that selector above that applied to the portion (which itself is set simply as .portion-class tag).
See:
Harry Roberts: http://jsfiddle.net/csswizardry/3N53n/3/ - note use of .btn.btn on line 28.
mine: http://jsfiddle.net/Emsap/5/ - note use of .dash-heading.dash-heading on line 2
Note that I was, of course, wrong to think that the location of elements in the DOM was affecting the specificity.
If I have the following attribute:
html {
text-decoration: none !important;
}
But I wanted to allow one text-decoration, like 'line-through' to still be active...
Is it possible to do this? How?
Edit: I don't know what html this is applied to- it is dynamic through a browser plugin...
Thanks!
You can specify this attribute on your particular element/elements, like
.decorated {
text-decoration: line-through;
}
This way, the text-decoration value of none will not get inherited.
EDIT:
http://jsfiddle.net/mGGnc/ demonstrates this. This will, of course, never work if the decorated class is added to the HTML element, since in this case there will be no property value inheritance. CSS2 spec explains this.
If you will make separate a classes for your elements so than it will not get inherited from your reset css
You achieve your desired easily like this :-
html {
text-decoration: none;
}
.anchor a {
text-decoration:line-through;
color:red;
}
DEMO
The rule (not attribute) html { text-decoration: none !important; } has no impact, except in the rather hypothetical case where another style sheet sets the property on the root element, the html element. Contrary to popular misunderstanding, the text-decoration element is not inherited. When set to a value other than none, its effect partly resembles inheritance in a sense, though.
In a comment to an answer, you write: “this is a text-decoration reset css that removes all decorations- EXCEPT one or two that I would like to keep- like line-through”. As usual, general reset CSS stylesheets tend to cause problems rather than solve them. To override text-decoration settings on all elements, you would need to use the universal selector * (or a list of all known and unknown elements). But you cannot make it override settings that use some values and not override others, due to the way the property has been defined. Its value is either none or a space-separated list of keywords each specifying a “decoration”. So there is no way to just negate one of those keywords, without setting the property to a specific value.