Custom elements - hide an element before it can render - javascript

Using custom elements, is it possible to have an element's display set to none (or in any other way) before it renders? Consider that I am using this particular one as a base class for other elements, so applying a global style won't work.
The element is simple
<my-element></my-element>
And it doesn't do much :)
class MyElement extends HTMLElement {}
customElements.define('my-element', MyElement);
But a lot of others extend it
<my-other-element></my-other-element>
class MyOtherElement extends MyElement {}
customElements.define('my-other-element', MyOtherElement);
This is why I could not have a global css rule
my-element {
display:none;
}
I thought I got smart and added a shadow dom with a <style> and :host style but this just makes any other HTML I've placed inside my elements disappear.
Any ideas?

With the :defined pseudo class, which is part of the Web Components spec, you can apply styles whenever the custom element has been successfully defined.
my-element {
display: none;
}
my-element:defined {
display: block;
}

Related

How to I apply a custom style for a third-party component in a single React component without affecting its style in other components?

I am using a dropdown from react-bootstrap and its context-menu has a className called Select-menu-outer. I wanted to change the font size of this menu only in one component.
What I did was, I just created a new css file called panel.css and did import './panel.css; in my component.
In the panel.css, I applied the style to the Select-menu-outer like
.Select-menu-outer { font-size: 12px }
This worked fine, but it affected the font size of all other dropdowns in the entire app.
I would have used CSS Modules and do something like import style from './panel.css and do className={style.Select-menu-outer} something like that, but since this is a third-party library component, I wasn't sure if I can do that.
Any good way to make this work?
Add a new class list to the drop down you what to change called .Select-menu-outer-size
Then do this in your css:
.Select-menu-outer-size { font-size: 12px !important}
The !important overrides the other class.
Javascript could be used!
let's say that it is the 3rd dropdown on that page with this class: .Select-menu-outer
So we do:
var addclass = document.getElementsByClassName("Select-menu-outer").[2];
addclass.classList.add("Select-menu-outer-size");
Then add you css:
.Select-menu-outer-size { font-size: 12px !important}
Note: 0 is 1 and 1 is 2 etc. for document.getElementsByClassName("Select-menu-outer").[2];
Linkhttps://www.w3schools.com/jsref/tryit.aspfilename=tryjsref_document_getelementsbyclassname
You can use the bsPrefix prop to customize the class of your component, in order to style it via CSS.
Change the underlying component CSS base class name and modifier class names prefix. This is an escape hatch for working with heavily customized bootstrap css.
Source: React-Bootstrap docs
You can use inline-styles on that specific menu to override the default style.
OR
you can assign an id e.g. id="outer-menu" to that specific menu tag and access that menu with #outer-menu in CSS.
The priority of id is greater than className so it will probably override it.

How to Prevent Css applying to other Files?

In this React Component I have Cookbook.js and Cookbook.css. I have a bunch of styles in Cookbook.css and specifically it has
form {
display: inline-block !important;
padding-top: 30px;
margin-left: 100px;
}
Which is fine since I import that into the Cookbook.js. But I created another Component called Survey.js along with Survey.css. In Survey.js I use a form as well but I ONLY import survey.css. Yet for some reason, The CSS from Cookbook.css gets applied to the form in my Survey.js. As a result, my form on Survey.js is in a odd spot. How Can I ensure that the css for each form is independent of each other?
When you create CSS rules, it is often easier to use class names instead of id's. Such as:
.class {
background-color: blue;
}
When you have common elements across multiple components, the CSS color will apply the styling to all elements such as:
p {
background-color: blue;
}
If you want to differentiate the styling where it applies in one component but does not apply to another which I think you are trying to do in your case, you need to use id's instead of element or class names.
Add an id to the component that you want to style and create a rule for that element such as:
#hero {
background-color: bluel;
}
This should be able to ensure that CSS is different from each other.
I think that you are looking for CSS modules. CSS modules are CSS files that only apply to a single component. Here is an example: https://css-tricks.com/css-modules-part-1-need/. More about CSS modules can also be found on Google and other forums.
Thank you,
Caiden Sanders.
In React when a component is mounted, its specific CSS file is also imported. You should know that React makes only a single HTML page application. In one HTML page if you import multiple CSS files and if they have conflicting CSS, then CSS will be applied on the basis of priority.
CSS that comes last overrides existing if common elements conflicting unless you haven't used !important with any property.
So, you should use unique ids or classes to prevent conflicts wherever required, and use common CSS if you have similar behaviour for certain elements.

Pseudo element manipulation

I have this DOM
<div class="slotvideo">
<div class="posterimage"></div>
</div>
I can't modify this html code but I need to add an SVG icon. This SVG is used for a function. On click I need to reach the bottom of the page. I create this CSS
.posterimage::before {
content: "";
background-image: mysvg;
}
Now, I can't manipulate pseudo element but I can't find another solution for doing it. How could you fix this problem?
I couldn't find what do you actually want. but about manipulating pseudo-elements, it's not possible. But there is a work-around.
You can define another class name like .active change the element's class to it for controlling pseudo-element.
.posterimage {
/* anything... */
}
.posterimage.active::before {
content: "";
background-image: mysvg;
}
don't forget, psuedo-elements are inline by default, so if you want this background-image to show up, you need to make it display: block and define a set of width and height though.
and it's done. you can use that .active class to have controll of showing ::before or not by JavaScript.

How to prevent Vue.js from automatically merging CSS classes?

I recently started working with Vue.js and I really enjoy it but I have come across something that I just can't figure out how to do. I have searched and read the documentation but found no solution.
When you add a CSS class to any of your components Vue.js will automatically add or merge the CSS classes with the root element in your child component.
This is a nice feature but I need to deactivate this feature for a specific component since I want the classes to be added to a child element of the root element.
I made this fiddle to illustrate http://jsfiddle.net/rasmuswoelk/9m2j0a9s/3
<div id="demo">
<child-component class="some-class"></child-component>
</div>
(The "some-class" is being added automatically and adds a green background color)
How can I prevent Vue.js from automatically merging CSS classes?
Updated
I disagree that it is intuitive to have a class that is applied to a component be moved by that component to an inner element, so my recommendation is still: Pass it as a prop.
However, it is possible to do what you want to do, with some caveats. The component will have a list of classes that belong on the outer element. In mounted, it looks at $el.classList and finds the classes that are not among the known outer element classes. Those get applied to the inner element and removed from the outer element. Caveat: if one of the outer element classes is applied to the component, it will not be moved to the inner element. And any updates to the applied class will not be caught.
Vue.component('child-component', {
template: `<div :class="outerClasses"><h1 :class="childClasses">Hello</h1></div>`,
data() {
return {
outerClasses: ['child'],
childClasses: []
};
},
mounted() {
this.childClasses = Array.from(this.$el.classList).filter((c) => !this.outerClasses.includes(c));
for (const c of this.childClasses) this.$el.classList.remove(c);
}
});
var demo = new Vue({
el: '#demo'
});
.child {
border: 1px solid red;
padding: 20px;
text-align: center;
}
.some-class {
background-color: green;
}
<script src="//vuejs.org/js/vue.min.js"></script>
<div id="demo">
<child-component class="some-class a b c"></child-component>
</div>
I think that you will want to wrap the whole thing in another <div></div> as Vue will merge the classes on the top element. If you just want the style for <h1> then try doing this:
template: `<div><h1 class="child">Hello</h1></div>`
This should give you the expected behavior, let me know if it doesn't work.
You can't abstract away the wrapper div that you have in your template, and trying to make the component work in such as way as though that div doesn't exist will only lead to confusion and incorrect styling.
Let's say that you managed to get your component to apply the outer class to a nested element in its template (which is what you want). Now when people use that component and apply a class to it, the style is applied to the input element and it is as though the whole component consists solely of the input element and there is no such wrapper div (this is the behavior you want).
The problem with this is that some styles will work (like background-color, or any appearance style), but other styles that affect the layout won't work (like position: absolute, because it will cause the input element to be positioned relative to the wrapper div which is not what was expected).
People who use that component should know about how the template is structured so they can style it correctly, because in reality there is a wrapper div there which they need to take into account.
I should mention you might be able to abstract away the wrapper div by using web components or the shadow DOM, but that's out of context of Vue.
A more simpler way (imo) is to bind the incoming class attribute and dynamic class prop to the data and remove them from the vnode (virtual node) during the created() hook.
Vue.component('child-component', {
template: `
<div class="child">
<h1 :class="staticClass">Hello</h1>
</div>
`,
data() {
return {
staticClass: [],
}
},
created() {
// dynamic :class prop
this.staticClass.push(this.$vnode.data.class)
// delete if not applying on this.$el
delete this.$vnode.data.class
// static class attr
this.staticClass.push(this.$vnode.data.staticClass)
// delete if not applying on this.$el
delete this.$vnode.data.staticClass
},
});
var demo = new Vue({
el: '#demo',
data: {
dynamicClass: 'dynamic-class'
},
});
.child {
border: 1px solid red;
padding: 20px;
text-align: center;
}
.some-class {
background-color: green;
}
.dynamic-class {
border: 1px solid yellow;
}
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.min.js"></script>
<div id="demo">
<child-component :class="dynamicClass" class="some-class"></child-component>
</div>

Applying CSS Styling to Child Based on Ancestor Class

OK - I have a pretty basic page that I'm trying to keep as simple as possible. I have a "theme selector" that chooses between a light and dark theme, and sets the body's class based on that, basically changing from white/black background/text. I have boxes within that are a different background color that also need to change... is there a way to change the applied class of a child (perhaps many removed) based on the class of the body tag (or any ancestor for that matter) using CSS?
Simple demo:
<body class="dark">
<div class="container">
<div class="differentBG">THIS IS THE BOX I WANT TO CHANGE!</div>
</div>
</body>
I know I can use js (d3 is what I'm using) to apply a class to all of the children, but I want to keep as much in CSS as possible...
You can base rules off of ancestor classes on the body tag as you would any other tag in your markup:
body.dark .differentBG {
background: black;
color: white;
}
Our differentBG class will apply a black background only when the <body> has a class of "dark".
body.light .differentBG {
background: white;
color: black
}
Our differentBG class will apply a white background when <body> has a class of "light".
As an added bit of trivia, many developers use this very technique to setup their "JavaScript Disabled" styles:
body.nojs .dynamicElement {
display: none;
}
And then use JavaScript to remove that class when the page loads. Modernizr also uses this method, though it adds classes to the <html> element to indicate what features the user agent supports.

Categories