use styled-components to share styles between components/elements - javascript

I am using styled-components along with Gatsby. I used styled-components to style the Link component provided by Gatsby for my home page.
const HomePageLink = styled(Link)`
display: inline-block;
font-size: ${fontSizes.xxlarge};
text-decoration: none;
box-shadow: none;
:link,
:visited {
color: ${colors.slate};
}
:hover,
:active {
color: ${colors.red};
}
`
However I realize that I also need to style a plain html <a /> tag using the exactly same style. I wonder is there a way to make the style component above adapt to <a /> tags without duplicating the code like this
const HomePageAnchorTag = styled.a`
display: inline-block;
font-size: ${fontSizes.xxlarge};
text-decoration: none;
box-shadow: none;
:link,
:visited {
color: ${colors.slate};
}
:hover,
:active {
color: ${colors.red};
}
`

Yes, use css API which allows you to construct reusable CSS blocks.
A helper function to generate CSS from a template literal with interpolations.
import styled, { css } from 'styled-components';
const reusableCSS = css`
display: inline-block;
font-size: ${fontSizes.xxlarge};
text-decoration: none;
box-shadow: none;
:link,
:visited {
color: ${colors.slate};
}
:hover,
:active {
color: ${colors.red};
}
`;
const HomePageAnchorTag = styled.a`
${reusableCSS}
`;
const HomePageLink = styled(Link)`
${reusableCSS}
`;
Usually, you will notice a mixins.js file that contains exports of reusable css block, for example:
// mixins.js
const flexCenter = css`...`
export default { flexCenter };
// usage inside styled components.
${mixins.flexCenter}

Related

why inline styling &:hover will not have any effect in react js

I'm trying to add hover effect to a span element as shown below.
Hover effect doesn't work when added inside
style prop.
But, If it is written in separate css file it will work
I just want to know, Why it is So?
https://codesandbox.io/s/happy-resonance-stqbf9?file=/src/App.js
App.js
import "./styles.css";
export default function App() {
return (
<div className="App">
<span
style={{
fontSize: "4em",
color: "blue",
"&:hover": {
color: "green"
}
}}
>
Element
</span>
<div></div>
<span className="ele">Element 2</span>
</div>
);
}
styles.css
.App {
font-family: sans-serif;
text-align: center;
}
.ele {
font-size: 4em;
color: blue;
}
.ele:hover {
font-size: 6em;
color: green;
}
You need to use JSS Plugin which supports the psudo-selectors inline style, or you should use Material UI, which also support this plugin.
That because we can't specify the inline styles for pseudo elements and pseudo classes. You can use it with the,
Internal - by using a <style> element in the section.
An internal CSS is defined in the section of an HTML page, within a element.example
External - by using a element to link to an external CSS file
To use an external style sheet, add a link to it in the section of each HTML page.example

SASS Mixin typography issue while implementing multi language

I am working on a react website which use sass for managing styling. So in the website I have implemented typography for english language through sass mixins.
There are different headings and bodies in the typography like heading1, heading2 , body1, body2 etc . Format of each element in typography is like
#mixin body1{
font-size:10px,
font-weight: 700,
letter-spacing: 1px,
line-height:1
}
#mixin body2{
font-size:5px,
font-weight: 400,
letter-spacing: 1px,
line-height:1
}
And then I include this body in my component css like :
.primaryButton .text{
#include body1;
}
.secondaryButton .text{
#include body2;
}
so button is single component is react , we are just changing parent class based on variation props and so its styling .
Now the issue is that I have to implement typography for different languages like about 50 languages and I an not sure what generic approach will be best to implement .
Note :
We didn't use generic classes instead of mixin for typography because we have variation and theme for each component and for each variation and theme same element may have different font size and other properties so for different variation we load different typography elements based on component parent class.
Also I don't want to go in each file and then overwrite english typography based on parent class for each language as project size is too big for that and also 50 languages is also too many for that approach. And in future language can increase .
you can use like this
Placeholders
%body1{
font-size:10px;
font-weight: 700;
letter-spacing: 1px;
line-height:1;
}
%body2{
font-size:5px;
font-weight: 400;
letter-spacing: 1px;
line-height:1;
}
%body3{
font-size:5px;
font-weight: 400;
letter-spacing: 1px;
line-height:1;
}
Configs
$langsConfig: (
"en": (body2),
"fr": (body1, body2),
"cn": (body2, body3),
"bn": (body1, body2, body3),
);
css generator
#each $lang, $placeholderList in $langsConfig {
.#{$lang} {
.primaryButton {
.text {
#each $placeholder in $placeholderList {
#extend %#{$placeholder}
}
}
}
}
}
Output
.bn .primaryButton .text, .fr .primaryButton .text {
font-size: 15px;
font-weight: 700;
letter-spacing: 1px;
line-height: 1;
color: red;
}
.bn .primaryButton .text, .cn .primaryButton .text, .fr .primaryButton .text, .en .primaryButton .text {
font-size: 20px;
font-weight: 400;
letter-spacing: 1px;
line-height: 1;
color: green;
}
.bn .primaryButton .text, .cn .primaryButton .text {
font-size: 25px;
font-weight: 400;
letter-spacing: 1px;
line-height: 1;
color: yellow;
}
React implementation
export default function App() {
const lang = "en";
return (
<div className={`${lang}`}>
<div className="primaryButton">
<h1 className="text">Hello CodeSandbox</h1>
<h2 className="text">Start editing to see some magic happen!</h2>
</div>
</div>
);
}
Explanation:
Placeholder: Instead of mixing use placeholder.
Config: Language name and related mixing list
Generator: it will make a loop with configs and create the css is dynamic ways
NOTE: if you want to use component based scss. Then create a scss function and pass the variables in css generator.
Here is the Sandbox link
Let me know if it helps. It could be more dynamic if i could know the implementation on react side.

Change Element's Class Name without affecting CSS values

I have an DOM element and I want to only change the className of the element. I want to remain the css values as it. (For both external css and inline css)
For example, if I have this:
.sample{
display: block
font-size: 10px,
font-color: #fff
}
<div class="sample">...</div>
After doing some JavaScript operation I need to reach this:
.newCss{
display: block
font-size: 10px,
font-color: #fff
}
<div class="newCss">...</div>
Note: There is no strict rule for css, there can be a css selector with 100 values or with only 1 one.
Note2: There is no css selector such as .newCss, I should transform the css properties from .sample, to a new one called .newCss
You can get the computed style for the element prior to making the change:
const style = getComputedStyle(theElement);
and then apply that styling to the element directly:
theElement.style.cssText = style.cssText;
Then removing the class won't change the element's styling, because it's styled inline.
Example:
const theElement = document.querySelector(".sample");
console.log("before:", theElement.className);
setTimeout(() => {
const cssText = getComputedStyle(theElement).cssText;
theElement.className = "newCss";
theElement.style.cssText = cssText;
console.log("after: ", theElement.className);
}, 800);
.sample{
display: block;
font-size: 10px;
color: #fff;
background-color: black;
}
.newCss {
background-color: yellow;
}
<div class="sample">this is the div</div>
If the new class has styling associated with it in CSS, that might affect the styling of the element. If you need to prevent that, change the class first, then assign the CSS text:
Example:
const theElement = document.querySelector(".sample");
console.log("before:", theElement.className);
setTimeout(() => {
theElement.style.cssText = getComputedStyle(theElement).cssText;
theElement.className = "newCss";
console.log("after: ", theElement.className);
}, 800);
.sample{
display: block;
font-size: 10px;
color: #fff;
background-color: black;
}
<div class="sample">this is the div</div>
You have to use JavaScript. In order to use JavaScript, you have to assign a ID to the <div> tag. Then manipulate it by JavaScript. Example: document.getElementById("id1").className="sample";
Also make sure that you using semicolon(;) after CSS properties.
function f1()
{
document.getElementById("id1").className="sample";
}
.sample{
display: block;
font-size: 10px;
font-color: #fff;
color: red;
}
.newCss{
display: block;
font-size: 10px;
font-color: #fff;
color: green;
}
<div id='id1' class="newCss"><p>Hello</p></div>
<button onclick="f1()">Click</button>
Well, if you want to change className to a class which is identical, you can simply redefine the class in the style sheet to be equivalent, or you can use inline styles, but the purpose of CSS classes is to keep a unique set of rules, so two identically-ruled CSS classes would defeat the purpose for which they exist, to be unique definitions of CSS rules, so if you want the CSS rules exactly the same, then there wouldn't be a reason to change the className, unless you were referencing it with other JavaScript functions, or if you wanted to add additional styles while keeping the old ones, in such a case:
use classList to dynamically add or remove certain individual classes, while keeping others.

How to set padding of Gatsby Link Component to 0px with styled-components

I have made some style changes to the Gatsby Link component using styled-components. However for some reason, when i try to apply a padding of 0px, it still leaves a tiny space (few px) above/below the text (between text and top/bottom border). I used gatsby-default-starter in a codesandbox for the initial build.
HTML/CSS Env (codepen.io):
https://codepen.io/marti2221/pen/mNVJWZ
Gatsby Env (codesandbox):
https://codesandbox.io/s/gatsby-paddinglink-spacing-gedtq
I have tried applying padding via styled-components in a Gatsby environment, as well as a normal html/css environment. When padding is set to 0px on the "a" tag in css/html environment, there is no space around the text, as expected. However when i attempt to add the same padding to the gatsby Link component or even a regular a tag, in a gatsby environment, there is a tiny space between the text and my border. This leads to a larger padding on top/bottom for my BtnLink than expected. I could adjust my padding accordingly, but i would like to know the root cause of this issue.
const StyledLink = styled(Link)`
display: inline-block;
font-family: sans-serif;
border-radius: 25px;
padding: 0px;
text-decoration: none;
border: 2px solid green;
`
const StyledA = styled.a`
display: inline-block;
font-family: sans-serif;
border-radius: 25px;
padding: 0px;
text-decoration: none;
border: 2px solid green;
`
const BtnLink = props => (
<StyledLink {...props}>{props.children}</StyledLink>
)
const IndexPage = () => (
<Layout>
<BtnLink to="page-2">Request Quote</BtnLink>
<StyledA href="page-2">Request Quotes</StyledA>
<Link to="page-2">Link</Link>
</Layout>
)
My desired result is a gatsby Link component that can be styled the same as a regular link element (ie. 0px padding). My result is link text with some spacing around it in the Gatsby environment. When tested with regular HTML/CSS, results are as expected (no spacing when padding is set to 0px)
You've already made a styled(Link) styledComponent, and saved it to the const StyledLink.
const StyledLink = styled(Link)`
display: inline-block;
font-family: sans-serif;
border-radius: 25px;
padding: 0px;
text-decoration: none;
border: 2px solid green;
However, this won't have any affect on a regular gatsby Link component. You still need to render this new StyledLink styledComponent instead of a gatsby Link component if you want to see that styled variation on your page.
const IndexPage = () => (
<Layout>
<BtnLink to="page-2">Request Quote</BtnLink>
<StyledA href="page-2">Request Quotes</StyledA>
<StyledLink to="page-2">Link</StyledLink>
</Layout>
)

Updating the Styling of a component passed in - ReactJS

I am fairly new to React and I am stuck in styling a component using styled components.
const SearchBarContainer_Button = styled.button`
padding: 10px;
margin-left: 10px;
width: 300px;
`;
<ButtonOne
style={SearchBarContainer_Button}
type="submit"
className="search-bar__button"
>
{this.props.buttonText || 'search'}
</ButtonOne>
Here is what I have in my ButtonOne:
import React from 'react';
import styled from 'styled-components';
const Button_One = styled.button`
cursor:pointer;
border: none;
background-color: #fff;
color: #000;
font-size: 12px;
font-weight: 900;
`;
export const ButtonOne = (props) => (
<Button_One className={props.className}>{props.children}</Button_One>
);
I have no idea what I am doing wrong, and I would really appreciate some guidance.
Thank you.
Hmm did you read the documentation for styled components? they are styled COMPONENTS
which means when you specify
const Button_One = styled.button`
cursor: pointer
`
you need to use it as component
<Button_one ...props />
You can't pass style={StyledComponent} it's component not object literal with style. IF you want to extend the styled components here is the link https://www.styled-components.com/docs/basics#extending-styles
When used styled-components, you're creating a new component with a certain styles. For your search bar, you're creating a component named SearchBarContainer_Button as that is your variable name. You do not need to add the style again. Try reviewing the documentation, or reference this example;
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: red;
`;
And to use your component Title with the specified styles:
<Title>Content of component</Title>

Categories