I have two buttons with classnames of "app__footer-card-email" and "app__footer-card-mobile".
They are the same buttons css wise except they have different background colours.
What are some efficient methods of reducing repetition in scss in this scenario? I am even looking for multiple options so i can apply the principle to other instances of scss aswell. Thanks!
HTML
const Footer = () => {
return (
<>
<div className="app__footer">
<h3 className="head-text">Want to reach out?</h3>
<h3 className="head-text">Lets have a chat over some coffee.</h3>
<div className="app__footer-cards">
<div className="app__footer-card-email">
<img src={images.email} alt="email"/>
edwin.huang9#gmail.com
</div>
<div className="app__footer-card-mobile">
<img src={images.mobile} alt="mobile"/>
0415560320
</div>
</div>
</div>
</>
)
}
SCSS
.app__footer-card-mobile {
width: 360px;
display: flex;
justify-content: flex-start;
align-items: flex-start;
margin: 2rem;
border: radius 0%;
background-color: #d0e2fe;
opacity: 0.7;
border-radius: 10px;
padding: 10px;
flex-direction: row;
align-items: center;
}
.app__footer-card-email {
width: 360px;
display: flex;
justify-content: flex-start;
align-items: flex-start;
margin: 2rem;
border: radius 0%;
background-color: #ffc9d0;
opacity: 0.7;
border-radius: 10px;
padding: 10px;
flex-direction: row;
align-items: center;
}
Like the others have said, split out the shared properties into their own class, then change based on your variations (mobile, email, etc.).
You're already using SASS, so you can use nesting here to keep everything together nicely.
I've renamed the classes so you can see one way this could be done with BEM naming, but you can adjust to whatever suits best for you.
You should however use appropriate semantic elements.
.footer-card {
background-color: var(--background-color, #f2f2f2);
width: 360px;
display: flex;
justify-content: flex-start;
align-items: flex-start;
margin: 2rem;
border: radius 0%;
opacity: 0.7;
border-radius: 10px;
padding: 10px;
flex-direction: row;
align-items: center;
&--mobile {
--background-color: #d0e2fe;
}
&--email {
--background-color: #ffc9d0;
}
}
const Footer = () => {
return (
<>
<footer className="footer">
<h3 className="footer__heading">Want to reach out?</h3>
<p className="footer__body">Lets have a chat over some coffee.</p>
<div className="footer__cards">
<div className="footer__card footer__card--email">
<img src={images.email} alt="email"/>
hi#example.com
</div>
<div className="footer__card footer__card--mobile">
<img src={images.mobile} alt="mobile"/>
55555555
</div>
</div>
</footer>
</>
)
}
Buttons and cards are something you'll find yourself repeating often, so it can also be smart to make yourself a mixin or function to do this more handily.
You can do this with CSS by moving the shared CSS properties into a common class, which is most efficient because there will be no unnecessarily duplicated CSS across classes.
.app__footer-card-mobile {
background-color: #d0e2fe;
}
.app__footer-card-email {
background-color: #ffc9d0;
}
.app__footer-card {
width: 360px;
display: flex;
justify-content: flex-start;
align-items: flex-start;
margin: 2rem;
opacity: 0.7;
border-radius: 10px;
padding: 10px;
flex-direction: row;
align-items: center;
}
<h3>Want to reach out?</h3>
<h4>Lets have a chat over some coffee.</h4>
<div class="app__footer-card app__footer-card-email">
<img src="" alt="email" />
edwin.huang9#gmail.com
</div>
<div class="app__footer-card app__footer-card-mobile">
<img src="" alt="mobile" />
0415560320
</div>
You can create a general class name with the similarities of your two buttons classes and then extend the general class in your custom styles; Like below:
.btn{
width: 360px;
display: flex;
justify-content: flex-start;
align-items: flex-start;
margin: 2rem;
border: radius 0%;
opacity: 0.7;
border-radius: 10px;
padding: 10px;
flex-direction: row;
align-items: center;
}
.app__footer-card-mobile {
#extend .btn;
background-color: #d0e2fe;
}
.app__footer-card-email {
#extend .btn;
background-color: #ffc9d0;
}
Related
I have a layout which I can't achieve.
Here is an example of how it should behave.
I thought best way would be using grid, but I am opened to suggestions. So it should have width: auto, but if there is task.comment - width of task should become 100% of container and height should be responsive to task.comment content.
<div className='tasks-preview'>
{tasks.map(task => (
<div className='task'>
<div className="text-container">
<p className="task-name">{task.name}</p>
<p className="task-hour">{task.hour}h</p>
</div>
{task.comment ? <div className="comment-container">
<CommentIcon />
<p className="task-comment">{task.comment}</p>
</div> : null}
</div>))}
</div>
My CSS looks like this:
.tasks-preview {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(70px, max-content));
gap: 12px;
.task {
display: flex;
flex-direction: column;
justify-content: flex-start;
background: $light;
color: $main-text;
width: fit-content;
height: 22px;
padding: 4px 6px;
border-radius: 4px;
.text-container {
display: flex;
align-items: center;
gap: 6px;
p {
margin: 0;
}
}
.comment-container {
display: flex;
gap: 8px;
color: $main-accent;
.task-comment {
display: flex;
}
}
}
}
Currently I have this layout and don't know how to move forward because it's far from what I need:
I have a collection of a couple of divs (called buttons) inside a div container.
When attempting to resize the screen to check for responsiveness, (trying to keep them centered in the middle of the screen) instead of shrinking, the buttons FIRST get clipped from (or hide behind) both sides of the screen.
here is my code:
.button {
outline: 1px solid black;
min-width: 0;
min-height: 0;
width: 10rem;
height: 10rem;
flex: 1 0 1rem;
}
.container {
display: flex;
align-items: center;
justify-content: center;
}
.parentContainer {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
Below are the global styles:
html,
body {
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
display: flex;
justify-content: center;
}
The html is made using components:
<div className={parentContainer}>
<div className={container}>
<HeaderButton />
<HeaderButton />
<HeaderButton />
<HeaderButton />
<HeaderButton />
<HeaderButton />
</div>
</div>
The header button component:
const Button = () => {
return (
<div className={button}>
<h1>{props.text}</h1>
</div>
)
}
export default Button;
Any idea how I might achieve what I'm aiming for?
Thank you for the help.
That's most probably due to the buttons having fixed width.
I'd suggest adding a responsive variant for the .container
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
#media only screen and (min-width: 600px) {
.container {
flex-direction: row;
}
}
This will make the buttons fall one below the other.
Please use flex-wrap: wrap
.container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.item {
width: 100px;
height: 50px;
margin: 5px;
background: #000000;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
Use display flex for responsiveness and percentages for element widths:
body{
width:100%;
height: 100vh;
display:flex;
justify-content: center;
align-items: center;
}
.container{
width:100%;
height:100px;
display:flex;
justify-content: center;
align-items: center;
flex-direction: row;
flex-wrap: wrap;
}
.d1,.d2,.d3,.d4,.d5{
width:100px;
height:100px;
border:2px solid black;
}
<div class="container">
<div class="d1"></div>
<div class="d2"></div>
<div class="d3"></div>
<div class="d4"></div>
<div class="d5"></div>
</div>
Ok so first I'd like to thank everyone for their responses, but the solution that I needed was in fact aspect-ratio:
.button {
width: 80%;
aspect-ratio: 1 / 1;
}
.container {
display: flex;
align-items: center;
justify-content: center;
margin-top: 5%;
width: 90vw;
gap: 3.5%;
}
I'm just doing some learning material on Codeacademy and I'm wanting to know how to control the space between the "locations" text and the three divs below. The assignment is asking me to create a 15px space between them but I don't know how to do that. Currently, there is just a default space that I don't know how is calculated.
html {
text-align: center;
}
.location-container {
background-image: url(https://content.codecademy.com/courses/freelance-1/unit-4/img-locations-background.jpg);
height: 700px;
width: 1200px;
display: flex;
justify-content: center;
align-content: center;
flex-wrap: wrap;
}
#local {
background-color: blueviolet;
}
.location-columns {
display: flex;
justify-content: center;
width: 100%;
gap: 30px;
color: white;
}
.locations {
background-color: black;
width: 300px;
}
<div class="location-container">
<h2 id="local">Locations</h2>
<div class="location-columns">
<div class="locations">
<h3>Downtown</h3>
<h5>384 West 4th St</h5>
<h5> Suite 108</h5>
<h5>Portland, Maine</h5>
</div>
<div class="locations">
<h3>East Baysuide</h3>
<h5>3433 Phisermans Avenue</h5>
<h5>(Northwest Corner)</h5>
<h5>Portland, Maine</h5>
</div>
<div class="locations">
<h3>Oakdale</h3>
<h5>515 Crescent Avenue</h5>
<h5> Second Floor</h5>
<h5>Portland, Maine</h5>
</div>
</div>
Thanks for any insights.
Heading elements come with large upper and lower margins right from the default browser styles.
You can remove those for elements inside .locations, make it a flex container and use row-gap to control vertical spacing:
html {
text-align: center;
}
.location-container {
background-image: url(https://content.codecademy.com/courses/freelance-1/unit-4/img-locations-background.jpg);
height: 700px;
width: 1200px;
display: flex;
justify-content: center;
align-content: center;
flex-wrap: wrap;
}
#local {
background-color: blueviolet;
}
.location-columns {
display: flex;
justify-content: center;
width: 100%;
gap: 30px;
color: white;
}
.locations {
background-color: black;
display: flex;
flex-direction: column;
row-gap: 30px;
padding: 30px;
width: 300px;
}
.locations>* { margin: 0; }
<div class="location-container">
<h2 id="local">Locations</h2>
<div class="location-columns">
<div class="locations">
<h3>Downtown</h3>
<h5>384 West 4th St</h5>
<h5> Suite 108</h5>
<h5>Portland, Maine</h5>
</div>
<div class="locations">
<h3>East Baysuide</h3>
<h5>3433 Phisermans Avenue</h5>
<h5>(Northwest Corner)</h5>
<h5>Portland, Maine</h5>
</div>
<div class="locations">
<h3>Oakdale</h3>
<h5>515 Crescent Avenue</h5>
<h5> Second Floor</h5>
<h5>Portland, Maine</h5>
</div>
</div>
counter.js
import "./Counter.css";
const Counter = (props) => {
return (
<div className="counter">
<h1>{`Counter ${props.count}`}</h1>
<div className="counter__buttons">
<button onClick={props.incrementCounter}>Increment</button>
<button onClick={props.decrementCounter}>Decrement</button>
</div>
</div>
);
};
Counter.css
.counter {
display: flex;
color: white;
align-items: center;
width: 100%;
height: 100%;
}
.counter > .counter__buttons > button {
color: black;
background-color: grey;
margin: 10px;
padding: 30px;
border: 0;
border-radius: 10px;
}
i want to move the buttons below counter and place the counter and buttons in the center of the page how to change it , display : flex in counter should not be removed
Would something like this work? You can set the flex-direction of a wrapping div to column and set the second div (in your case your buttons) back to flex-direction: row and finally just center it with margin: 0 auto.
<div id="wrap">
<div id="one">1</div>
<div id="two">2
<div id="three">3</div>
<div id="four">4</div>
</div>
</div>
#wrap {
display: flex;
flex-direction: column;
}
#two {
display: flex;
flex-direction: row;
margin: 0 auto;
}
Do you want something like this?
.page {
background: black;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100vh;
}
.counter {
display: flex;
flex-direction: column; /* add this */
color: white;
align-items: center;
/* width: 100%;*/
/* height: 100%;*/
}
.counter > .counter__buttons > button {
color: black;
background-color: grey;
margin: 10px;
padding: 30px;
border: 0;
border-radius: 10px;
}
<div class="page">
<div class="counter">
<h1>Counter 5</h1>
<div class="counter__buttons">
<button onClick={props.incrementCounter}>Increment</button>
<button onClick={props.decrementCounter}>Decrement</button>
</div>
</div>
</div>
If so, you can make your whole page a flex container and use justify-content and align-items just like you did it for the .counter.
(I did HTML instead of JSX so I could add the snippet easier... don't forget to make changes in your own code)
When using position: fixed, the browser will remove the original place the layout thing have. How to prevent it?
In my case, the actual fixed position of a search appbar act as
Expecting act as.
Simulating css code.
.search-appbar-container {
position: fixed;
display: flex;
flex-direction: row;
align-items: center;
width: 100%;
height: 48px;
}
.lef-arrow-icon-container`
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
width: 60px;
`;
.search-textfiled-container`
display: flex;
flex: 1;
flex-direction: row;
align-items: center;
`;
.add-icon-container`
display: flex;
flex-direction: row;
align-items: center;
`;
.search-history-container {
display: flex;
flex-direction: column;
justify-content: center;
width: 100%;
margin-top: 5px;
}
.history-toggle-button`
position: relative;
width: 100%;
height: 48px;
background-color: transparent;
-webkit-box-sizing: border-box;
box-sizing: border-box;
border: none;
outline: none;
-webkit-appearance: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-tap-highlight-color: transparent;
`;
.history-icon-container`
position: absolute;
top: 11.5px;
left: 0;
width: 60px;
`;
.history-text-container`
position: absolute;
top: 11.5px;
left: 60px;
display: flex;
flex-direction: row;
align-items: center;
`;
Simulating html code.
<div>
<div class="search-appbar-container">
<div class="left-arrow-container>
...
</div>
<div class="search-textfield-container>
...
</div>
<div class="add-icon-container>
...
</div>
</div>
<div class="search-history-div">
<button class="history-toggle-button">
<div class="history-icon-container>
...
</div>
<div class="history-text-container>
...
</div>
</button>
</div>
</div>
EDIT
Have checkout all of my code, now I can find why this happened.
If the position of .search-appbar-container is static, the absolute position of history-icon-container and history-text-container are related the relative position of history-toggle-button, otherwise they are all related fixed position of search-appear-container.
you can set margin-top or padding-top to .search-history-div or set .search-history-div{position: fixed;top: 48px}
After searching and trying by myself, I have come out with a idea. If you want to keep fixed div with a block level, the proper way is to wrapper the same size parent div over it. Reflecting to my case, add the same width and height wrapper div upper search-appbar-container
.search-appbar-container-wrapper {
width: 100%;
height: 48px;
}
.search-appbar-container {
position: fixed;
...
width: 100%;
height: 48px;
}
...
<div class="search-appear-container-wrapper">
<div class="search-appbar-container">
...
</div>
</div>
...