adding Border animations with dynamic classes in React with SCSS - css

I have a HeaverNav component, a pretty simple fixed position header. When the user scrolls past a certain dimension a class is added that just adds a border-bottom to the existing class. Applying an animation for the border to enter is simple enough with a
transition: all 300ms ease; But having the border animate out when the class is no longer active is tricky. Currently the border just flips off suddenly with no smoothness, how can I achieve the effect of the border animating out smoothly?
MY CODE
import React, { useEffect, useState } from 'react';
import navStyles from '../styles/nav-header.module.scss';
import { MdOutlineAddBox } from 'react-icons/md';
import { RiHeartLine } from 'react-icons/ri';
import { FiSend } from 'react-icons/fi';
const NavHeader = () => {
const [isScrolling, setIsScrolling] = useState(false);
console.log(isScrolling)
useEffect(() => {
if (typeof window !== "undefined") {
window.addEventListener("scroll", () =>
setIsScrolling(window.pageYOffset > 100)
);
}
}, []);
return (
<nav className={isScrolling ? `${navStyles.nav} ${navStyles.navIsScrolling}` : `${navStyles.nav}`}>
<h1>Instagram</h1>
<ul>
<li><MdOutlineAddBox /></li>
<li><RiHeartLine /></li>
<li><FiSend /></li>
</ul>
</nav>
)
}
export default NavHeader;
SCSS
#import "../styles/global.scss";
#font-face {
font-family: "Instagram";
src: url("../assets/instagram-font.otf") format("woff2");
}
.nav {
display: flex;
align-items: center;
justify-content: space-between;
position: fixed;
width: 100%;
padding: 0.8rem;
background-color: $color-black;
h1 {
font-family: "Instagram", sans-serif;
color: $color-white;
font-size: 2rem;
}
ul {
display: flex;
margin-right: 1.5rem;
li {
color: $color-white;
font-size: $icon-size;
margin: 0 0.5rem;
transform: translateY(2px);
cursor: pointer;
}
}
}
.navIsScrolling {
border-bottom: $nav-border;
transition: all 300ms ease;
}

Related

How to change CSS of a child component from parent component

I have a react component called TeamBanner like so
import styles from "./teamBanner.module.css";
import { useNavigate } from "react-router-dom";
import { TeamBannerProps } from "../ProjectTypes.types";
export const TeamBanner = ({
team,
onBannerClick,
showName,
}: TeamBannerProps) => {
let navigate = useNavigate();
const handleOnClick = () => {
navigate(`/${team}`);
onBannerClick();
};
return (
<div
className={`${styles.container} flex theme-light ${
showName ? "" : styles["no-name"]
}`}
title={team}
onClick={handleOnClick}
>
<div>
<img
src={require(`../logos/${team}.svg`)}
alt="logo"
className={`${styles.logo} ${showName ? "" : styles["only-logo"]}`}
/>
</div>
{showName ? team : ""}
</div>
);
};
The teamBanner.module.css file is like so
.container {
margin: 0.25em;
align-items: center;
cursor: pointer;
top: 0;
z-index: 2;
background-color: hsl(var(--color-background));
padding: 0.1em 0.25em;
border-radius: 0.5em;
box-shadow: 0.05rem 0.05rem 0.2rem rgb(0 0 0 / 50%);
font-family: var(--ff-serif);
font-size: var(--fs-200);
}
.logo {
display: inline-block;
vertical-align: middle;
width: 3vmax;
height: 3vmax;
}
.container:hover {
outline: 0.15em solid hsl(240, 90%, 67%);
}
.no-name {
border-radius: 0.25em;
}
.only-logo {
width: 5vmax;
height: 5vmax;
}
I am using it to create a list of team of a page & this works just fine.
However, I want to use it in another place also. In the place, the to now want the .container:hover effect & I want the font properties of the .contaner and width & height properties of the .logo changed.
How can I accomplish this? only changing these items of the module.css? Can any one help? Thanks

How to center Items in react

Im crating a navbar for a cite and currently formatting the page Im pretty new to react so im trying to start with the basics. I am stuck on how to center my NavBarLinks, I have used text-center and position to make the links be in the center of the navbar but if I make the web browser smaller it wont stay in the center. My question is what is the right to center items in react.
import React, { useState } from "react";
import {
NavbarContainer,
TopContainer,
BottomContainer,
NavbarExtendedContainer,
NavbarInnerContainer,
NavbarLinkContainer,
NavbarLink,
Logo,
OpenLinksButton,
NavbarLinkExtended,
} from "../styles/Navbar.style";
import LogoImg from "../assets/logo.png";
function Navbar() {
const [extendNavbar, setExtendNavbar] = useState(false);
return (
<NavbarContainer extendNavbar={extendNavbar}>
<NavbarInnerContainer>
<TopContainer>
<NavbarLinkContainer>
<OpenLinksButton
onClick={() => {
setExtendNavbar((curr) => !curr);
}}
>
{extendNavbar ? <>✕</> : <> ≡</>}
</OpenLinksButton>
<Logo src={LogoImg}></Logo>
</NavbarLinkContainer>
</TopContainer>
<BottomContainer>
<NavbarLinkContainer>
<NavbarLink to="/"> Home</NavbarLink>
<NavbarLink to="/products"> Products</NavbarLink>
<NavbarLink to="/contact"> Contact Us</NavbarLink>
<NavbarLink to="/about"> About Us</NavbarLink>
</NavbarLinkContainer>
</BottomContainer>
</NavbarInnerContainer>
{extendNavbar && (
<NavbarExtendedContainer>
<NavbarLinkExtended to="/"> Home</NavbarLinkExtended>
<NavbarLinkExtended to="/products"> Products</NavbarLinkExtended>
<NavbarLinkExtended to="/contact"> Contact Us</NavbarLinkExtended>
<NavbarLinkExtended to="/about"> About Us</NavbarLinkExtended>
</NavbarExtendedContainer>
)}
</NavbarContainer>
);
}
export default Navbar;
Style page
import styled from "styled-components";
import { Link } from "react-router-dom";
export const NavbarContainer = styled.nav`
width: 100%;
background-color: black;
#media (min-width: 700px) {
height: 80px;
}
`;
export const TopContainer = styled.div`
padding-left: 5%;
`;
export const BottomContainer = styled.div`
padding-right: 50px;
background-color:salmon;
`;
export const NavbarInnerContainer = styled.div`
width: 100%;
height: 80px;
`;
export const NavbarLinkContainer = styled.div`
display: flex;
`;
export const NavbarLink = styled(Link)`
color: white;
font-size: x-large;
font-family: Arial, Helvetica, sans-serif;
position: relative;
left: 43%;
top:10%;
text-decoration: none;
margin: 10px;
height: 30px;
text-align: center;
#media (max-width: 700px) {
display: none;
}
`;
export const NavbarLinkExtended = styled(Link)`
color: white;
font-size: x-large;
font-family: Arial, Helvetica, sans-serif;
text-decoration: none;
margin: 10px;
`;
export const Logo = styled.img`
#media (min-width: 700px) {
margin: auto;
}
margin: 10px;
max-width: 180px;
height: auto;
`;
I really wouldn't recommend using a whole different page for css instead just add your code to index.css, from there you can access your css from any component in your react app.
And to center the NavbarLink you can use flexbox.
Create some css code in index.css:
.navbar__link {
width: 100%
display: flex;
justify-content: center;
}
And add that class in your component element:
<NavbarLinkContainer className='navbar__link'>
<NavbarLink to="/"> Home</NavbarLink>
<NavbarLink to="/products"> Products</NavbarLink>
<NavbarLink to="/contact"> Contact Us</NavbarLink>
<NavbarLink to="/about"> About Us</NavbarLink>
</NavbarLinkContainer>

Styled-Components mobile menu

I'm trying to achieve the following result. I have a responsive menu, however when the screen is less than 768px should hide a few elements (the ItemsMenu and LanguageItems) from the horizontal menu that it is for the desktop and display in the burger menu for mobile.
I'm having an issue because if I use display: none; it'll hide in both displays, for desktop and for mobile. How would be a better approach to achieve this result:
Component:
function Languages() {
const [language, setLanguage] = useState("en");
const handleLanguage = (language) => (event) => {
setLanguage(language);
};
return (
<>
<Lang>
<Logo>
<h1>Flávio</h1>
</Logo>
<ItemsMenu>
<li>{languages[language].about}</li>
<li>{languages[language].project}</li>
<li>{languages[language].contact}</li>
</ItemsMenu>
<LanguageIcon>
<img src={English} alt="EN" onClick={handleLanguage("en")} />
<img src={Japanese} alt="JP" onClick={handleLanguage("jp")} />
<img src={Russian} alt="RU" onClick={handleLanguage("ru")} />
<img src={Portuguese} alt="PT-BR" onClick={handleLanguage("ptbr")} />
</LanguageIcon>
</Lang>
</>
);
}
Styled-component:
import styled from "styled-components";
export const Lang = styled.div`
display: flex;
justify-content: space-between;
margin: auto;
width: 100%;
li:hover {
transition: all 0.2s ease-in-out;
transform: scale(1.5);
}
`;
export const Logo = styled.div`
color: #2e186a;
cursor: pointer;
`;
export const ItemsMenu = styled.ul`
display: flex;
justify-content: center;
cursor: pointer;
color: #2e186a;
margin: auto;
li {
display: inline-block;
color: #2e186a;
cursor: pointer;
padding-left: 1.5rem;
}
#media (max-width: 768px) {
/* display: none; */
}
`;
export const LanguageIcon = styled.div`
#media (max-width: 768px) {
/* display: none; */
}
img {
height: 2em;
margin-left: 1em;
cursor: pointer;
}
img:hover {
transition: all 0.2s ease-in-out;
transform: scale(1.5);
}
`;

How to apply CSS transition on hide?

I have a bootstrap navbar that on collapse displays the items outside of it. When collapsing I have a div that works as an overlay that covers the whole page, so the navbar menu does not stay on top of any content of the page. The problem happens when I hide the menu: the div disappears immediately and during the hiding transition of the menu it stays on top of the page's content.
I want to keep the menu transition, so how can I apply a transition to the div when it is hiding? I've tried a lot of approaches but all of them only apply the transition when the div shows and not when it hides.
Check this demo, please: https://codesandbox.io/s/d31eo
React (demo):
import React, { Component } from "react";
import { Container, Nav, Navbar } from "react-bootstrap";
import "./styles.css";
import "bootstrap/dist/css/bootstrap.min.css";
export default class NavBar extends Component {
constructor(props) {
super(props);
this.state = {
open: false,
data: []
};
}
componentDidMount() {
this.setState({
data: [
{ name: "Test1" },
{ name: "Test2" },
{ name: "Test3" },
{ name: "Test4" }
]
});
}
onClick = () => {
this.setState({ open: !this.state.open });
};
render() {
return (
<>
<Navbar
className={`nav ${this.state.open ? "open" : ""}`}
expand="lg"
sticky="top"
>
<Container>
<Navbar.Toggle aria-controls="navbar-menu" onClick={this.onClick} />
<Navbar.Collapse id="navbar-menu">
<Nav className="ml-auto">
{this.state.data.map((category) => (
<Nav.Link href="#" key={`category-${category.name}`}>
<span className="link">{category.name}</span>
</Nav.Link>
))}
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
<div className={`overlay ${this.state.open ? "open" : ""}`} />
<img src="https://images.unsplash.com/reserve/bOvf94dPRxWu0u3QsPjF_tree.jpg?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MXwxMjA3fDB8MXxzZWFyY2h8Nnx8bmF0dXJhbHx8MHx8fA&ixlib=rb-1.2.1&q=80&w=1080" />
</>
);
}
}
CSS (demo):
.nav {
min-height: 55px;
width: 100%;
background-color: white;
border-bottom: 1px solid #979797;
}
.link {
font-size: 14px;
color: #3e433e;
line-height: 17px;
padding: 5px;
text-transform: uppercase;
}
.link:hover {
color: #000000;
text-decoration: none;
}
.overlay {
position: fixed;
}
#media (max-width: 1170px) {
.collapsing {
position: absolute !important;
z-index: 3;
width: 100%;
top: 75px;
}
.collapse.show {
display: block;
position: absolute;
z-index: 3;
width: 100%;
top: 75px;
}
.overlay.open {
height: 100%;
width: 100%;
position: fixed;
z-index: 2;
top: 55px; /* navbar min-heigth */
left: 0;
background-color: white;
}
}
Can you please check the below link code? Hope it will work for you. We have moved all declarations of .overlay.open to .overlay and added transition to .overlay(Default State), we don't need to add transition in .overlay.open.
For smooth transition we have added transition in height and opacity in Default State
transition: opacity 0.4s ease-in-out, height 0.4s ease-in-out.
1. In Default state - .overlay:
height set to '0px' and opacity set to '0'.
2. In Open state - .overlay.open:
height set to '100%' and opacity set to '1'.
Please refer to this link: https://codesandbox.io/s/summer-microservice-6d4c6
Step 1:
Move the styles of the overlay to its base css definition. leave in the .open only the css which should change on open. In our case we will change the height, so add height:0 to base .ovelay css and height:100% to .overlay.open
Step 2:
Add a css transition (e.g. transition: height .5s ease) to the base css, and set tansition: none to .overlay.open. this way the transition will apply only when its not have .open class. So it wll openinstantly, and close animated.
Hopefully this was the desired output:
https://codesandbox.io/s/charming-drake-dbtce?file=/src/styles.css
There is no need for the overlapping div for cover full body. We can manage it by the CSS property.
Use the following code for solving your problem.
React code:
import React, { Component } from "react";
import { Container, Nav, Navbar } from "react-bootstrap";
import "./styles.css";
import "bootstrap/dist/css/bootstrap.min.css";
export default class NavBar extends Component {
constructor(props) {
super(props);
this.state = {
open: false,
data: []
};
}
componentDidMount() {
this.setState({
data: [
{ name: "Test1" },
{ name: "Test2" },
{ name: "Test3" },
{ name: "Test4" }
]
});
}
render() {
return (
<>
<Navbar
className={`nav ${this.state.open ? "open" : ""}`}
expand="lg"
sticky="top"
>
<Container>
<Navbar.Toggle aria-controls="navbar-menu" />
<Navbar.Collapse id="navbar-menu">
<Nav className="ml-auto">
{this.state.data.map((category) => (
<Nav.Link href="#" key={`category-${category.name}`}>
<span className="link">{category.name}</span>
</Nav.Link>
))}
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
<img src="https://images.unsplash.com/reserve/bOvf94dPRxWu0u3QsPjF_tree.jpg?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MXwxMjA3fDB8MXxzZWFyY2h8Nnx8bmF0dXJhbHx8MHx8fA&ixlib=rb-1.2.1&q=80&w=1080" />
</>
);
}
}
CSS Code:
.nav {
min-height: 55px;
width: 100%;
background-color: white;
border-bottom: 1px solid #979797;
}
.link {
font-size: 14px;
color: #3e433e;
line-height: 17px;
padding: 5px;
text-transform: uppercase;
}
.link:hover {
color: #000000;
text-decoration: none;
}
#media (max-width: 991px) {
#navbar-menu {
position: fixed;
top: 57px;
left: 0;
right: 0;
background-color: #fff;
padding: 0 10px;
height: 0 !important;
transition: height 0.3s ease-out !important;
-webkit-transition: height 0.3s ease-out !important;
overflow: hidden;
}
#navbar-menu.show {
height: calc(100vh - 57px) !important;
}
}

How to slide OUT modal without using jQuery?

Is there a way that I could slide out my modal which slides in?I've written a code that makes the modal slide in from left to right and I cant figure out how to slide out the modal. Can anyone help me with this? When the user clicks on the x button, the modal should slide out from right to left.
Thanks in advance!!
.headerContactModal {
background-color: white;
color: #1a66b1;
margin-left: 15px;
height:70px;
width:100%;
padding-top: 20px;
font-weight: 700;
}
.headerContactModalMessage {
padding-left: 20px;
padding-right: 5px;
}
.headerContactModalExit{
z-index: 999;
float: right;
display: inline;
color: $dark_gray;
position: absolute;
top: 5px;
}
.headerContactModalPhone {
font-size: 18px;
padding-right: 10px;
}
.slidein {
animation-duration: 700ms;
animation-name: slidein;
animation-iteration-count: 1;
animation-direction: alternate;
}
#keyframes slidein {
from {
margin-left:100%;
}
to {
margin-left:0%;
}
}
import React, { PropTypes, Component } from 'react';
import classNames from 'classnames';
import Button from '../../../common_ui/leafs/Button';
import GenericTextField from '../../components/GenericTextField';
import Icon from '../../../common_ui/leafs/Icon';
class HeaderContactModal extends Component {
static propTypes = {
phoneNumber: PropTypes.string,
messageText: PropTypes.string
}
static defaultProps = {
phoneNumber: '1-800-CALLUS',
messageText: 'Call us:'
}
render() {
return (
<div className="headerContactModal slidein">
<span className="headerContactModalMessage">{this.props.messageText}</span>
<span className="headerContactModalPhone">{this.props.phoneNumber}</span>
<span onClick={this.props.contractContactUs}><Icon className="fa-close headerContactModalExit"/></span>
</div>
);
}
}
export default HeaderContactModal;
What you're looking for is ReactCSSTransitionGroup. Simple addon to react to handle transition animations when moving between states (such as open/closed on your modal).

Resources