I have a <style> element that applies some global styles, like A { color: red } as opposed to my stylesheet that styles A { color: green } (purely as an example).
How can I modify all of the styling in my <style> element so that are "contained" and only apply the styling to children of a parent element I specify.
A { color: red } becomes #myelem A { color: red }
.myclass { display: none; } becomes #myelem .myclass { display: none }
Would I have to find the <style> element, parse the contents, replace each selector then update the element contents with it fixed?
Is there an alternative to modifying the contents of my <style> element?
Why am I doing this? I have HTML that is stored in a database that I want to edit (this is a CMS). The HTML can contain <style> elements, and I cannot trust who writes the CSS to write it in scope. I could prevent users from using the <style> element, but I'd rather not. I have no control over the original CSS. Only what I get back in my server/clientside code.
If all else fails, I might have to load it into an iFrame... :(
Ooooooo Firefox supportes <style scoped> which only applies to the parent where the <style> element is located in the DOM. Too bad it's not supported in any other browser. :(
As you mentioned, you can use:
<style scoped>
...
</style>
Although it is only supported natively in Firefox, you can use this jQuery polyfill to get it to work in other browsers.
Use the child selector:
#yourElement > a { color: green; }
JQuery:
$( "parent_type > children_type" ).css("param","value");
example
$( "#myid > div" ).css("display","none");
here's a link
JSFiddle
Related
I would like to know how we can implement this code to work in chrome browser,
/* Selects any element with right-to-left text */
:dir(rtl) {
background-color: red;
}
https://developer.mozilla.org/en-US/docs/Web/CSS/:dir
what is the alternative in Chrome Browser?
Since you're using the dir HTML attribute, you can use a CSS attribute selector to style that element accordingly. In case it is not obvious, this is not the same thing as the :dir() pseudo-class in CSS. Attribute selectors are widely supported across all modern browsers.
For Chrome, you may need to apply the element to the <body> instead, or be prepared to use body { background-color: inherit; }:
html[dir="rtl"] {
background-color: red;
}
body {
background-color: inherit; /* Required for Chrome */
}
<html dir="rtl">
<body>
<div>A red document background</div>
</body>
</html>
You don't have to apply it to the whole document either, of course. You can apply it to a specific element only:
div[dir="rtl"] {
background-color: red;
}
<html>
<body>
<div>A white background</div>
<div dir="rtl">A red background</div>
</body>
</html>
If you would like to use JavaScript to detect the dir attribute, you can do so this way (or Google for your favorite way to detect an element via JS... there are at least half a dozen different ways):
/* EcmaScript 6 required, which shouldn't be an issue for modern Chrome, Firefox, Edge, etc. */
const doc = document.querySelector('html');
if (doc.hasAttribute('dir')) {
const textDir = doc.getAttribute('dir');
if (textDir == 'rtl') {
doc.classList.add('rtl');
} else {
doc.classList.add('ltr');
}
}
.rtl {
background-color: red;
}
body {
background-color: inherit; /* again, only needed for Chrome */
}
.ltr {
/* whatever styles you want for LTR text direction */
background-color: green;
}
<html dir="rtl">
<body>
<div>A red document background</div>
</body>
</html>
:dir() is indeed very useful since it refers to the direction of the element even if inherited from the parent or ancestor, but unfouruntately it's only supported in Firefox as you mentioned.
[dir="rtl"] is supported cross-browser, but it only refers to elements that have this specifically. If the entire document is one direction and it is specified in either the <html> or <body> tag, then that's not a big problem since you can simply use the descendant selector. For example
[dir="rtl"] p {
background: red;
}
However, this becomes complicated in a bidirectional document with nested sections. For example
<body dir="rtl">
<p>עברית (RTL text)</p>
<div dir="ltr">
<p>English (LTR text)</p>
<div dir="rtl">
<p>עברית (another RTL text)</p>
</div>
</div>
</body>
Sure, you can apply style rules to both directions like this
[dir="ltr"] p {
background: green;
}
[dir="rtl"] p {
background: red;
}
but CSS does not care which ancestor is closer, so the code above would still apply red to all paragraphs (and even reversing the order of rules wouldn't help for the nested section).
What you can do in this case is using CSS variables, which are inherited. For example
[dir="ltr"] {
--p-background: green;
}
[dir="rtl"] {
--p-background: red;
}
p {
background: var(--p-background);
}
In this case the variable is applied directly to the element with the specified direction, then the variable value is inherited through the element chain the same way the direction itself does, and affects the styling of the element defined to use the variable value - in this example the <p> element.
I'm making a plugin that dynamically generates a container on any page.
Because there might be some predefined rules that change the appearance of the contents inside my .my-plugin, so I set
.my-plugin * {
all: inital;
}
to the <style> tag inside of it.
But somehow it makes the <style> tag visible:
/* The style that from the page, which is uncertain */
h1 {
color: red;
}
<h1>This is red</h1>
<!-- dynamically injected code -->
<div class="my-plugin">
<style>
.my-plugin * {
/* reset everything to default state */
all: initial;
}
.my-plugin {
border: solid 1px black;
}
</style>
<h1>This is not red</h1>
</div>
How do I set everything inside a tag back to their initial states?
I know I can do something like .my-plugin style { display: none; }, but what about other tags that should not be invisible as well?
Ultimately I just don't want the h1 inside .my-plugin to be red.
Is there a better approach?
initial for display is inline for all elements which obviously includes style elements. This overrides the display:none style applied by the user-agent style sheet.
To get the styles as they were before the author styles start being applied, what you really want is { all: revert; } but the browser compatibility is not good yet.
The easy answer is, just include
paper-button{
background: black;
}
, but that wouldn't restyle the element if it is contained in another element. The solution used to be
html /deep/ paper-button{
background: black;
}
which still works fine, but is deprecated from the Shadow DOM spec. So what is the proper solution?
PS. Purely to be complete in case it somehow matters: What I actually want to reproduce properly is
html /deep/ paper-button.main{
[...]
}
You can use CSS custom properties to change the paper-button style globally.
Since paper-button exposes the --paper-button mixin, you can try the following inside your document -
<style is="custom-style">
simple-dialog, paper-button {
--paper-button: {
background-color: black;
color: white;
};
}
</style>
Have a look at this plunker.
When I add such CSS into <style> tags:
* {
display:block;
}
It is never interpreted correctly. Instead, what do I see? Somehow everything inside <style> becomes the part of html body. E.g.:
* {
display:block;
}
<p>paragraph</p>
<phrase>phrase</phrase>
<pet>pet</pet>
This happens anywhere. For the first time, I thought this is the problem with StackSnippets. (i.e. the live demo for Stack Overflow, the one I've provided above), but then I checked with code pen. Then with jsfiddle. Then I've gone ahead and made a file on my server, giving it all contents I inserted in the snippet above.
The outcome is always the same. The CSS gets included in the html, though it is applied. (the only fix is to create a stylesheet and include it using <link>)
The most interesting thing, is, that it seem to happen only with display:*. E.g., the following works:
* {
color:green;
background:red;
border:2px solid orange;
border-radius:5px;
}
<p>paragraph</p>
<phrase>phrase</phrase>
<pet>pet</pet>
But once I put in the styles of the last snippet display:*, the styles are, again, magically included in HTML.
* {
color:green;
background:red;
border:2px solid orange;
border-radius:5px;
display:inline-block;
}
<p>paragraph</p>
<phrase>phrase</phrase>
<pet>pet</pet>
Why does it happen?
It's styling the <head> element and everything in it, including the very <style> element your CSS resides in, because the CSS appears as character data within the <style> element. A <link> element on the other hand doesn't have any content — it points to a separate resource altogether, so there is nothing inside the element itself to be displayed.
Most browsers implement <head> as display: none (and some propagate that value to every descendant), which you are able to override by targeting them with a display style. The rest of the properties are still applied to <head> and its descendants regardless of whether you do this, but without it, they simply won't show up in your page so you don't really see it happening. That's really all there is to it — there isn't anything else that's special about <head> or its related elements.
In other words, as far as CSS is concerned, the following (yes, a <style> element with a style attribute...):
<style style="display: block; font-family: monospace">
p { color: red; }
</style>
Is no different from this:
<code style="display: block; font-family: monospace">
p { color: red; }
</code>
I have looked at several other questions but I can't seem to figure any of them out, so here is my problem: I would like to have a div or a span, when you hover over it an area would appear and would be like a drop down.
Such as I have an div, and I want to hover over it and have it show some info about the item I hovered over
<html>
<head>
<title>Question1</title>
<styles type="css/text">
#cheetah {
background-color: red;
color: yellow;
text-align: center;
}
a {
color: blue;
}
#hidden {
background-color: black;
}
a:hover > #hidden {
background-color: orange;
color: orange;
}
</styles>
</head>
<body>
<div id="cheetah">
<p>Cheetah</p>
</div>
<div id="hidden">
<p>A cheetah is a land mammal that can run up 2 60mph!!!</p>
</div>
</body>
</html>
But this ^ doesn't seem to work, I don't know why... and if there is a way to do that in CSS, I would like to know, but I want any and all suggestions.
You can achieve this in CSS only if the hidden div is a child of the element you use for hovering:
http://jsfiddle.net/LgKkU/
You cannot affect a non-child element using :hover from within CSS2, which is supported by all common browsers.
You can affect a sibling element using CSS2.1 selectors, like so:
a:hover + .sibling { ... }
However, this only works for direct siblings. This means you could have HTML like this:
<p>Cheetah <span class="sibling">Blah Blah Blah</span></p>
Notice that the a and the span are direct siblings.
Here's a fiddle showing the siblings working: http://jsfiddle.net/vUUxp/
However, not all browsers support the CSS2.1 sibling selectors, so you need to decide based on your target audience if you can use this or not.
Edit: Corrected my mistake on the CSS version for the + selector: it's 2.1 that defines it, not CSS3. I also added a link showing browser support. Otherwise, the answer is the same.
Or, if you're open to it, use jQuery.
Something like this would work:
$("#element") // select your element (supports CSS selectors)
.hover(function(){ // trigger the mouseover event
$("#otherElement") // select the element to show (can be anywhere)
.show(); // show the element
}, function(){ // trigger the mouseout event
$("#otherElement") // select the same element
.hide(); // hide it
});
And remember to wrap this in a DOM ready function ($(function(){...}); or $(document).ready(function(){...});).
You can absolutely do this in CSS3 now using the ~ adjacent sibling selector.
triggerSelector:hover ~ targetSelector {
display: block;
}
For example, if you want a tooltip to appear when hovering over an adjacent button:
.button:hover ~ .tooltip {
display: block;
}