styled-components - create class method? - javascript

I need a way to create classes without styled nor css method.
Lets assume proper style system with components having only basic styles, but not positioning, margin etc.
e.g.
const Root = styled.div`/* Some styles */`
export const MyComponent = ({className}) => <Root className={className} />
So this is easy, I attach private styles for component and I allow it to receive and apply class from parent.
If I have "classic" css, I would use it like this
import styles from 'some-styles.module.css';
...
<MyComponent className={styles.someStyle} />
Which will work as expected.
Here is the problem:
How do I create a class with styled-components only? It was working with Glamorous once, but SC (and Emotion) is not returning class name from css.
I can't use separate css files just to allow this styling, which should be common use case (parent setting size of children)
Edit & solution in Emotion
I figured out that Emotion adds extra property css which is available for every jsx element.
It can be used to native <div>, styled <Div> or custom React component <MyComponent.
Babel is changing css attribute with css({...}) to className during compilation.
If <MyComponent> only accepts prop className it will receive it from parent via css prop.

I still belive I should be able to somehow pass styles from parent to child.
There is a way to do that, but no exactly the way you want to do.
In react js (you can't do this in React Native yet), you can pass the child component inside the parent style and it will add the style in the child when it's wrapped by the parent.
e.g.
const ParentComponent = styled.div`
${ChildComponent} {
/* Child css*/
}
`
Sorry if formatting is bad, I'm on mobile

Related

How to protect svelte component from outer css styles

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?

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

React performance - DOM styling and component rendering

Can someone please explain what happens when I change the CSS class of a React component?
Let's say I have this code:
import React, {useState} from "react"
const Comp = props => {
const [class, setClass] = useState('visible')
if (props.hide) {
setClass('hidden');
}
return (<p className={class}>some text</p>)
}
My understanding of the process is this one:
Something in the parent component triggers a state change determining the Comp child to be called with property "hide" set to true
React will reconstruct the virtual DOM and the resulting html node of Comp will have the class set to "hidden"
React will update the DOM
Browser will render the DOM and apply the new styling
Am I correct?
Some related questions:
a. If the applied CSS class is just hiding the component, wouldn't be more efficient just to apply some conditional logic inside React parent component and don't display it at all?
b. If applying styling to html node just triggers the browser's painting method, why should we link CSS classes to the app state, thus triggering a full rendering? For me it seems inefficient.

How to overwrite material-ui className with aphrodite?

I'm using React and styling some icons. I'm using the Material-UI library for my components. One of the components I'm using is the FontIcon . It already has a className on it, and I'm not able to override with my passed in aphrodite style.
<FontIcon className="material-icons">
bug_report
</FontIcon>
If I set the style on this control, it works fine:
<FontIcon className="material-icons" style={{ color: 'red' }}>
bug_report
</FontIcon>
How can you over-write an existing className? I've tried:
className={css(['material-icons', styles.colorize])}
className={css('material-icons', styles.colorize)}
className={('material-icons', css(styles.colorize))}
Thanks!
The issue is that this component doesn't allow to pass a custom className property, only the ability to extend with the style one as you can see in their PropTypes definition.
Material-ui is using a style in JS form, and doesn't really want to deal with "normal" CSS, even though I agree sometimes it's easier to override.
You could wrap your component in a div that you give your custom className and stylize the children instead. Appart from doing a pull request, there is not much choice.

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.

Categories