How to protect svelte component from outer css styles - javascript

I have page index.html which includes file styles.css ( .foo{width:100%; ..... and other styles} )
via
<link href="styles.css">
And also this page includes svelte application
Svelte application has component with same class name .foo
<div class="foo"></div>
<style>
.foo{background-color:red;}
<style>
Svelte render it into something like this
<input class="foo svelte-12sas231dad">
Is there any method to protect my component's input from outer css ?
For example something to make
<input class="foo-svelte-12sas231dad">
without outer .foo class or may be another decision ?

The best solution is to not use global styles that accidentally apply where you do not want them to. I.e. remove the rules or use very specific class names that will not accidentally be used in components. Everything else is just a workaround to a fundamental problem you will run into again.
Given that Svelte adds classes with hashes you could target the element using a different method, e.g. just the tag type (input) or some data attribute.
As far as I know the only way to really isolate the element from styles would be adding an iframe which is far from ideal.

Are you using Sveltekit?
Perhaps you could use the The CSS !important Rule in your Svelte component styles.
Better yet, why not just change the class names?

Related

How to access content (innerText) of style tag in Vue Component programmatically for entire component?

For my current project I need to pass html (and styles) to puppeteer to generate a pdf from it.
I am accessing the html by using $ref.export.$el.innerHTML but how can I access the style? My workaround until now was to create a div that contains the same style attributes so I can access it as a ref aswell.
It is important to keep the original css syntax to be able to build html out of it afterwars. I also need to get the whole style for the component, not just for single elements.
First you need to access the ref and then you just need to access styles directly or get computed styles.
template
<!-- vm.$refs.p will be the DOM node -->
<p ref="p">hello</p>
Now you could access styles via this.$refs.p.style. If you want computed styles you would need helper function as in the example below.
script
methods: {
getStylesFromRef() {
// return this.$refs.p.style if you have style attributes
// following line for computed styles
return window.getComputedStyle(this.$refs.p)
}
}
I solved the issue by using <component> in my template with is="style", that way it is not removed during compile https://stackoverflow.com/a/57331310/8773697

Change CSS properties directly in Angular 2+

In jQuery, we can do
JQuery('.someStyle')
.css({"background", "red"})
to directly change the CSS property in style.
In Angular 2+, we can use [style.<property>] to manipulate, is there an option to directly manipulate the style sheet?
Angular offer template reference variable like this. Here #textCont is a template variable which can be passed to component and it can be used to add styles
<div #textCont> I wil change color on click<div>
<button type="button" (click)="changeColor(textCont)">Click</button>
In component
changeColor (elem){
elem.style.color="red"
}
DEMO
Even with the jQuery snippet you posted you don't manipulate the stylesheet, only the CSS properties of the object representing the DOM element.
Why would you want to manipulate the stylesheet directly? You would have to modify it before the browser parses it - before it is sent from server to client. This is hardly desirable.
What you are probably looking for is just a way how to change styles of your DOM element dynamically.
There are many ways how to achieve that with Angular ranging from injecting ElementRef (object providing access to component's host element) to your component's constructor or using Renderer2 in order to change the styles directly on the DOM element, to templating (like the [style.<property>] you have mentioned) or even Angular Animations.
Just fixed a small bug from #brk here. In Angular 13+ you may use:
<div #textCont> I wil change color on click</div>
<button type="button" (click)="changeColor(textCont)">Click</button>
And in Component more "strict typing"
changeColor(elem: { style: { color: string } }) {
elem.style.color = 'red';
}

How to change <body> tag style from child component?

I have this in index.html:
<body class="light-gray">
<app-root></app-root>
<div id="preloader">
<div></div>
</div>
</body>
In app-root i have this:
<laylout></laylout>
Inside layout i have one component where in scss i want to change body on index. Any suggestion how can i do that?
.light-gray{
background: red!important;
}
I tried :host but this is not main parent i need something like: :host :host :host. Host of host of host :)
Use ::ng-deep, like so:
CSS
::ng-deep .light-gray{
background-color: red;
}
DEMO
Use ViewEncapsutation.None:
CSS
.light-gray{
background-color:red
}
Class:
import { ViewEncapsulation } from '#angular/core';
...
#Component({
...
encapsulation: ViewEncapsulation.None
DEMO
To expand a little, View Encapsulation is the default, and it wraps all CSS defined within a view with extra selectors that limit it to only applying within the base object of the view.
It does this (from memory - may not be exactly correct) by adding an attribute to tags in that view (_ng_content-* being the usual format) and then modifying all the embedded CSS attached to the view to add a condition of [_ng_content-*]
So, for example,
A view with view encapsulation enabled might be allocated the attribute "_ng_content-c2".
As a result if its html was
<div class='mydiv'></div>
It would render as
<div _ng_content-c2 class='mydiv'></div>
and if the css for the view had
div.mydiv {color:black}
then the style block with the div would be
div.mydiv[_ng_content-c2] {color:black}
So if you add a body css entry
body {color:black}
it renders as
body[_ng_content-c3] {color:black}
and as a result avoids actually changing your body tag (because your body tag won't have that attribute)
View encapsulation is very useful for allowing clean class names in objects without worrying about namespace collision. It's particularly relevant for shared components where you can't be sure your class names aren't used elsewhere.
On the other hand it makes lots of standard CSS difficult or impossible.
Personally I just don't use it, and prefer to use singular central css files for the whole document, but I'm not suggesting that is best practice.
For those that are interested, here is one of the issues with view encapsulation...
If you have an encapsulated view within another encapsulated view it can be impossible for the outer views CSS to control the inner view as it will wrap it's CSS with the outer attribute, but the items in the inner view will have the inner attribute.
A possible fix to angular for this (but I'm not sure of its consequences) would be that inner views should have both their parents attribute as well as their own. This would become ugly though as the view stack grew.
Another feature I'd love to see would be a way to mark CSS items as not to be encapsulated or to only be "base encapsulated" (that being, encapsulation that only checked they existed within the base object where the CSS was, not that they were themselves created in the base object. That way you could have css like this...
div.taginbase {}
#noEncaps body {}
#baseEncaps div.taginchild
and this would render in the style tag as
div.taginbase[_ng_content_c] {}
body {}
[_ng_content_c] div.taginchild
This would then allow a view to define specific (and context aware) styling of view encapsulated child views.
Give your body an ID. Define a CSS class to be used by a particular component in the global styles.css or styles.scss. Then make sure your component implements AfterViewInit and OnDestroy.
Inside the functions required by these interfaces put:
ngAfterViewInit(): void {
document.getElementById("my-body-id").classList.add("specific-class");
}
ngOnDestroy(): void {
document.getElementById("my-body-id").classList.remove("specific-class");
}

Dynamic CSS stylesheets based using State Values in React

I am implementing a custom color theme module. Simply the user selects two separate colors (a primary and secondary that are ANY hex value) and save the value in state. I use these colors to set custom dynamic styles to components in my application such as:
<Link style={{backgroundColor: this.props.myprofile.primaryColor}} to={href} />
This was working fine except for 2 issues.
It takes forever adding the logic to each component. I would rather be able to set a className and call the logic on every element with that className.
Psuedo Classes. Psuedo Classes such as :hover and :focus do not mix well with inline styling. I know about and have used Radium, but I would prefer to find a different solution.
React doesn't have any special control over CSS classes, it's the same as vanilla javascript. So you won't be able to manipulate pseudo elements for the same reason.
1) You can use React's state to set a classname conditionally, inside the render method. In this example I'm using a module called classnames but you can handle this logic however you like.
render() {
const isActive = this.state.isActive
const styles = classNames({
button: true,
'is-active': isActive
})
return (
<div className={styles}></div>
)
}
/* evaluates to
<div className="button is-active"></div>
*/
2) There's no real solution for javascript with pseudo classes. The best you can do is add classes you've defined in your CSS files that have pseudo selectors already.
So it seems the best solution I could personally find was still using my style method, but I was also forced to use Radium.
The dynamic of what I am trying to do makes using inline styles a necessity it seems because a CSS stylesheet can not be set by state dynamically unless there is a class for every case on the hexadecimal chart (which is what I want as options for my Users).
NOTE: Is important to understand when viewing this that the main reason for this decision is because the options I want for the user is every value the hex color chart can yield.
This is a dreadful way of doing this needing apply a style attribute containing the logic, but for the sake of the feature must be done to every component. This beats writing a class for every hex value.
To solve the issue with Psuedo classes I am using Radium for use of :hover and :focus. Not the solution I wanted from my original question, but the best I've got at the moment.
So the code if using Psuedo Classes looks something like this...
import Radium from 'radium'
<div key={i} style={{backgroundColor: primaryColor, ':hover': {backgroundColor: 'yellow'}}} />
const radMyComponent = Radium(MyComponent)
export default connect(mapStateToProps, mapDispatchToProps)(radMyComponent)
If anyone has a better solution. Please post. I would love to see.

Removing effect of a CSS selector

My requirement is a bit tricky. I have a mark-up as below: (just an example, real mark-up is very complicated)
<div class="classA">
<div class="classB">
<p class="classC">
<span class="classD">
</span>
</p>
</div>
</div>
As you can see above, there are four CSS classes classA, classB, classC, classD associated with the markup.
Also I have used jQuery to bind events using these selectors.
My Requirement: I want the jQuery event binding to work and at the same time, the CSS should not get applied i.e. I want to negate the impact of CSS styles from a UI perspective, but from functional perspective jQuery event handlers should still work.
So, is it possible to override the CSS selectors such that their styles don't get applied to my mark-up elements ?
example below:
div.classA div.classB p.classC span.classD{
color:red;
}
I don't want the font color to be red, so I tried to override the selector as follows, but its not working:
div.classA div.classB p.classC span.classD{
color:red;
}
div.classA div.classB p.classC span.classD{
/*no styles here*/
}
Please help !!
Then just delete those classes from css. jQuery will still work though.
There is no requirement that only classes used in css have to be used in jquery.
For example:
<div class="someUnknownClass"></div>
Even though, there is no someUnknownClass defined in css, $('.someUnknownClass') will still work.
Use another class name for the selector. So you have classA for the css and classX for the selector.
If you don't want the styles applied. Then you could use $('selctor').css(); to over write the styles. Bit hacky!
OR.
Add a class that over-rides the css. Or remove the class that holds the css.
using: $('selctor').addClass('no_styles'); OR $('selctor').removeClass('current_styles');
I don't know any mechanism allowing to do that the way you want it.
the work around i would suggest would be binding your events on anoter css class and doing something like this :
$('.classD').addClass('eventClassD').removeClass('classD');
$('.eventClassD').on('myEvent', function(){...});
like this you will still have events binded to your elements and would get rid of all the css.
You want to do it without modifying the JS? There's no clean way to do that. But try this.
Presumably you will have something that distinguishes this special set of elements to distinguish it from other elements, of which styles' you want to retain. This is difference probably manifests itself in the form of a different parent container. Just copy the set of CSS rules that affect these classes, and prepend this parent CSS selector with the pre-class values.
"Basically, I do not want to touch the js code, and only if something can be done on the css front, then my requirement is achieved."
If that is all you need, then just remove all of the css definitions from the page.
$("link,style").remove()

Categories