How to use smooth-scroll from tailwindcss in React? - reactjs

I have created a one-page website using tailwindcss and React. In the prototype I use the tailwindcss class "scroll-smooth" and it works. In React the class "scroll-smooth" does not work, but what is the reason?
https://tailwindcss.com/docs/scroll-behavior#basic-usage
When I click "Why" on Navigation i jump to the section "why" but not smoothly:
function App() {
return (
<div className="App">
<div className="relative">
<div className="flex flex-col scroll-smooth">
<HomeNav />
<HomeHero />
<section id="why" className="flex flex-col items-center px-6 pt-20">
...
</section>
<HomeFooter />
</div>
</div>
</div>
);
}
Solution:
I think TailwindCss Class "scroll-smooth" it doesn't work on react. So I use the NPM package "react-scroll" with which it works great and I probably have less compatibility worries.
https://www.npmjs.com/package/react-scroll

react-scroll working superb but We can still use scroll-behavior: smooth with react and tailwindcss. Here is my solution:
Folder & File structure:
App.js :
import "./App.css";
import AntyHero from "./components/AntyHero";
import Footer from "./components/Footer";
import Hero from "./components/Hero";
import Navbar from "./components/Navbar";
function App() {
return (
<>
<section id="header">
<Navbar />
</section>
<div className="flex flex-col h-screen items-center justify-center additional gap-3">
<h1 className="text-5xl">TailwindCSS & React.js</h1>
<h2 className="text-3xl pb-5">smooth scrolling behavior</h2>
<div className="flex gap-5 items-center justify-center text-2xl underline bg-white rounded-md p-2">
<a href="#one" className="text-orange-600">
Section One
</a>
<a href="#two" className="text-red-600">
Section Two
</a>
<a href="#three" className="text-green-700">
Section Three
</a>
</div>
</div>
<div className="text-center text-3xl">
<section id="one" className="h-screen bg-orange-600">
Section One
</section>
<AntyHero />
<section id="two" className="h-screen bg-red-600">
Section Two
</section>
<Hero />
<section id="three" className="h-screen bg-green-700">
Section Three
</section>
</div>
<Footer />
</>
);
}
export default App;
index.css :
#tailwind base;
html {
scroll-behavior: smooth;
}
#tailwind components;
#tailwind utilities;
Output:
Tested with:"tailwindcss": "^3.0.11", "react": "^17.0.2" Firefox and Chrome

Add scroll-behavior: smooth to the code works for me.
#tailwind base;
#tailwind components;
#tailwind utilities;
#layer base {
html {
scroll-behavior: smooth;
}
}

Related

Storing Gatsby page content

I'm exploring Gatsby to make a static website with multiple pages. Those pages will have the same template, just the text will change. To make it easier, I'm going to create a single template. I want to store the content of the different pages (text, path etc.)in Yaml or JSON file. So basically it would look like this :
import React from "react";
import content from '../content/pageContent.yaml'
const Template = () => {
return (
<header className="div1">
<div className="flex items-center justify-center container mx-auto">
<div className="basis-1/2 el tagline">
<h1>{content.title}</h1>
<p>{content.description}</p>
<button>Lets go</button>
</div>
<div className="basis-1/2 el">
<img src=`../images/${pic}`
</div>
</div>
</header>
...
)
}
export template
Here is my pageContent.yaml
title: YAML content used at build time with Gatsby
description: my description with a <b>bold word</b>
pic: mypicture.png
Everything works great but the problem is that it doesn't render the HTML tags. But if I use <h1 dangerouslySetInnerHTML={ {__html: content.titre} }></h1> instead of <h1>{content.title}</h1> it renders the HTML tag.
My question is : is it ok to make it this way? Would it be a better way to do that ?
Thanks a lot
dangerouslySetInnerHTML exposes your app to security risks such as Cross-site scripting XSS attacks.
You could use a library like react-markdown to convert the markdown to html.
Here is an example of how you could do it, adapt as appropriate.
import React from "react";
import content from '../content/pageContent.yaml'
import ReactMarkdown from "react-markdown";
const Template = () => {
return (
<header className="div1">
<div className="flex items-center justify-center container mx-auto">
<div className="basis-1/2 el tagline">
<ReactMarkdown source={content.title} />
<ReactMarkdown source={content.description} />
<button>Lets go</button>
</div>
<div className="basis-1/2 el">
<img src=`../images/${pic}`
</div>
</div>
</header>
...
)
}
export template

Gatsby JS Portfolio Website poor cumulative layout shift on mobile devices [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 days ago.
This post was edited and submitted for review 7 days ago.
Improve this question
I have a problem with my portfolio website (Gatsby JS & Tailwind CSS framework)
the website: https://portfolio-revin.vercel.app/
github repo: https://github.com/revin212/portfolio-revin/
index.js code:
import * as React from "react"
import '/src/styles/tailwind.css'
import Layout from '/src/components/Layout.js'
import Hero from '/src/components/Hero.js'
import Skills from "../components/Skills"
import Projetcs from "../components/Projetcs"
import Contact from "../components/Contact"
import { Helmet } from "react-helmet"
import AOS from 'aos'
import 'aos/dist/aos.css'
import { useEffect } from "react"
export default function Home() {
useEffect(()=>{
AOS.init({
duration: 1700,
})
}, [])
return (
<Layout>
<Helmet>
<title>Revin's Portfolio</title>
</Helmet>
<main id="main-content" className=" text-neutral-white">
<div className='hero-section overflow-hidden bg-gradient-blue bg-cover bg-no-repeat
mt-[4.5rem] w-full'>
<Hero />
</div>
<div id='skills' className='skills-section overflow-hidden w-full bg-main-black px-[1.2rem] lg:px-[2rem] py-[4rem]'>
<Skills />
</div>
<div id='projects' className='projects-section overflow-hidden w-full bg-main-black px-[1.2rem] lg:px-[2rem] py-[4rem]'>
<Projetcs />
</div>
<div id='contact' className='contact-section overflow-hidden bg-gradient-blue bg-cover bg-no-repeat w-full px-[1.2rem] lg:px-[2rem] pt-[4rem] pb-[6rem]'>
<Contact />
</div>
</main>
</Layout>
)
}import * as React from "react"
import '/src/styles/tailwind.css'
import Layout from '/src/components/Layout.js'
import Hero from '/src/components/Hero.js'
import Skills from "../components/Skills"
import Projetcs from "../components/Projetcs"
import Contact from "../components/Contact"
import { Helmet } from "react-helmet"
import AOS from 'aos'
import 'aos/dist/aos.css'
import { useEffect } from "react"
export default function Home() {
useEffect(()=>{
AOS.init({
duration: 1700,
})
}, [])
return (
<Layout>
<Helmet>
<title>Revin's Portfolio</title>
</Helmet>
<main id="main-content" className=" text-neutral-white">
<div className='hero-section overflow-hidden bg-gradient-blue bg-cover bg-no-repeat
mt-[4.5rem] w-full'>
<Hero />
</div>
<div id='skills' className='skills-section overflow-hidden w-full bg-main-black px-[1.2rem] lg:px-[2rem] py-[4rem]'>
<Skills />
</div>
<div id='projects' className='projects-section overflow-hidden w-full bg-main-black px-[1.2rem] lg:px-[2rem] py-[4rem]'>
<Projetcs />
</div>
<div id='contact' className='contact-section overflow-hidden bg-gradient-blue bg-cover bg-no-repeat w-full px-[1.2rem] lg:px-[2rem] pt-[4rem] pb-[6rem]'>
<Contact />
</div>
</main>
</Layout>
)
}
When I open it on desktop browsers, it works fine and smooth, but on mobile devices, it's really laggy and I don't know what is the problem. I've tried removing the 'animation on scroll', and adding lazy loader to all images. But the lag is still there on mobile devices.
The animation on scroll library that I used for this website is 'aos':
https://www.npmjs.com/package/aos
From the vercel analytics feature, I found that the "cumulative layout shift" is the one that performs poorly, here is the analytics :
vercel website performance analysis image
Do you have any idea how can I improve the cumulative layout shift on mobile devices?
What I've tried:
removing the 'animation on scroll'
adding lazy loader to all images
compressing the png images

Adding a className dynamically in React.js with Tailwind.css

Let's say I have a React component that gets the Tailwind class name from props
for example :
import React from "react";
export default function Header({navColor}) {
return (
<nav
className="flex justify-center items-center text-white text-xl h-14"> //I want to add a class that it's name is the (navColor) value to the nav tag
TEST
</nav>
);
}
How can achieve this?
You can use Template literals to achieve that
Use ${} inside backticks ``
<nav
className={`flex justify-center items-center text-white text-xl h-14 ${navColor}`}>
TEST
</nav>
import classNames from "classnames";
import React from "react";
export default function Header({ navColor }) {
const headerClass = classNames(
"flex justify-center items-center text-white text-xl h-14",
navColor,
);
return <nav className={headerClass}>TEST</nav>;
}
classNames is also one of good option. You don't have to worry about misadding whitespace.

Background doesn't resize in responsive tailwindcss

I'm busing tailwindcss for my css. So for this I defined the image inside the tailwind config. Then I applied a cover on it but the image doesn't scale when I change the size of the screen. I thought by adding max-w-full min-h-full would fixe the problem but nothing.
import React from 'react'
import { CountdownEvent } from './CountdownEvent'
import { CarouselSaf } from './CarouselSaf'
import { Navbar } from './Navbar'
export const Home = () => {
return (
<section className="h-screen">
<div className="bg-safthon bg-no-repeat bg-cover max-w-full min-h-full">
<Navbar />
<div className="flex h-screen items-center">
<CountdownEvent />
</div>
</div>
</section>
)
}
Try to keep it simple. Check this demo.
<div class="min-h-screen max-h-screen bg-cover bg-center bg-no-repeat"
style="background-image: url('https://i.ytimg.com/vi/odM92ap8_c0/maxresdefault.jpg')">
</div>

having problems with context

i understand context and the ability to pass state down without prop drilling (to me it honestly seems like the same amount of work... i was using redux for global state management and besides the boilerplate the ability to use reducers, action creators, AND the redux dev tools makes it seem way more useful to me)
even using useContext hook the amount of code required is really the same fricking thing as just prop drilling to me... but maybe i'm missing something
ALL that aside.. i am currently trying to have a simple nav bar feature where when a burger menu is opened the backdrop of the home page turns to a faded darker opacity. i don't want a library. i like to do this all myself.
this is my App file. i was assuming i could just pass the state down (open) which would indicate if the nav is open. BUT HOW can i change the state of open IF THE only thing i can pass is open and not setOpen... i cant have an onClick event on the entire Nav bar component. i need the onclick even to be in the Nav, but all that is being passed is the state itself. every time i think i understand react some new unique situation comes up where i run into similar problems with state
// components
import Nav from './components/Nav'
import Homepage from './components/Homepage'
import React, {useState, createContext} from "react";
import {
BrowserRouter as Router,
Route,
} from "react-router-dom";
// pages
import About from './components/pages/About'
import Stories from './components/pages/Stories'
import News from './components/pages/News'
import ThemeContext from './ThemeContext';
// imports
function App() {
const [open, setOpen]=useState(false)
return (
<>
<Router>
<ThemeContext.Provider value={open}>
<Nav />
<Route path='/' exact>
<Homepage />
</Route>
<Route path='/about' component={About} exact />
<Route path='/stories' component={Stories} exact />
<Route path='/news' component={News} exact />
</ThemeContext.Provider>
</Router>
</>
);
}
export default App;
here is my nav component
import React, {useEffect, useState, useContext, useRef} from 'react'
import '../styles/custom.css'
import MenuDrop from './MenuDrop.js'
import {Link} from 'react-router-dom'
import ThemeContext from '../ThemeContext.js'
const Nav = () => {
const [active, setActive]=useState(false)
const [touched, setTouched]=useState(false)
const myRef=useRef()
const open=useContext(ThemeContext)
const clicker=()=>{
if(window.innerWidth<450){
setActive(!active);
}
}
useEffect(()=>{
console.log(open)
},[active])
const toucher=()=>{
setTouched(true);
}
const toucherOff=()=>{
setTouched(false);
}
return (
/* NAVBAR */
<>
<div className={`shadow-xl ${open?'dark':'light'}`}>
<div className='nav c overflow-hidden w-full nav-main md:pt-8 pt-4 flex justify-between md:justify-around items-center flex-row flex-shadow-2xl'>
<h1 className=' mx-2 antialiased text-lg md:text-3xl font-bold text-green-700 font-second-bold'>HUNTER SOLICITERS</h1>
<div className={`${active?'nav-items-active':'nav-items'} bg-white items-center md:items-center flex flex-col justify-center md:flex-row md:justify-around list-none w-1/3 flex-shadow-2xl`}>
<Link onClick={()=>setActive(false)} to='/about' className='lg:mt-0 mt-20 text-green-800 hover:text-green-800 font-semibold duration-200 antialiased p-2 cursor-pointer lg:my-0 my-6 text-sm lg:hover:text-white lg:hover:bg-red-900 font-main'>About</Link>
<li onClick={()=>setActive(false)} className='text-green-800 hover:text-green-800 font-semibold duration-200 antialiased p-2 cursor-pointer lg:my-0 my-6 text-sm lg:hover:text-white lg:hover:bg-red-900 font-main'>Contact</li>
<Link onClick={()=>setActive(false)} to='/stories' className='lg:mt-0 text-green-800 hover:text-green-800 font-semibold duration-200 antialiased p-2 cursor-pointer lg:my-0 my-6 text-sm lg:hover:text-white lg:hover:bg-red-900 font-main'>Stories</Link>
<Link onClick={()=>setActive(false)} to='/news' className='lg:mt-0 text-green-800 hover:text-green-800 font-semibold duration-200 antialiased p-2 cursor-pointer lg:my-0 my-6 text-sm lg:hover:text-white lg:hover:bg-red-900 font-main'>News</Link>
<div onMouseLeave={()=>toucherOff()} onMouseEnter={()=>setTouched(true)} className='flex flex-row items-center'>
<li onClick={()=>setActive(false)} className='text-green-800 hover:text-green-800 font-semibold duration-200 antialiased p-2 cursor-pointer lg:my-0 my-6 text-sm lg:hover:text-white lg:hover:bg-red-900 font-main'>Team</li>
<svg className='hover:bg-red-900 text-black hover:text-white arrowTwo' xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</div>
</div>
<div onClick={()=>clicker()} ref={myRef} className={active?'mx-2 burger-active ':'burger mx-2'}>
<div className={active?'toggle1 line-one':'line-one'}></div>
<div className={active?' toggle2 line-two':'line-two'}></div>
<div className={active?' toggle3 line-three':'line-three'}></div>
</div>
</div>
<MenuDrop toucher={toucher} setTouched={setTouched} toucherOff={toucherOff} touched={touched}/>
</div>
</>
)
}
export default Nav
and here is my homepage component
import React, {useContext, useEffect} from 'react'
// COMPONENTS
import Banner from './Banner'
import Footer from './Footer'
import GreenBanner from './GreenBanner'
import HomepageContentCards from './HomepageContentCards'
import HomepageContent from './HomepageContent'
import HomepageTeam from './HomepageTeam'
import WrappedMap from './Map'
import ThemeContext from '../ThemeContext'
import '../styles/custom.css'
// ASSETS
import imageTwo from '../images/home-image-two.jpg'
import imageThree from '../images/home-image-three.jpg'
import imageFour from '../images/home-image-four.jpg'
const Homepage = () => {
useEffect(()=>{
window.scrollTo(0, 0);
console.log(open)
})
const open=useContext(ThemeContext)
return (
<div className={`${open==='false'?'mt-0':'mt-20'} bg-container mt-10 md:mt-0 shadow-2xl`}>
<Banner />
<div className='shadow-xl grid grid-cols-1 gap-0 lg:gap-0 lg:grid-cols-12'>
<div class=" col-span-7">
<HomepageContent />
</div>
<div class="">
<HomepageTeam />
</div>
</div>
<GreenBanner />
<div className='grid grid-cols-1 gap-2 lg:gap-3 sm:grid-cols-3'>
<HomepageContentCards image={imageTwo}/>
<HomepageContentCards image={imageThree} />
<HomepageContentCards image={imageFour} />
</div>
<div className='mt-8 lg:mt-0'>
<WrappedMap
isMarkerShown
googleMapURL={`https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places$key=${process.env.REACT_APP_GOOGLE_KEY}`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `400px` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
</div>
<Footer />
</div>
)
}
export default Homepage
im using tailwind so ignore all the classes etc. basically im trying to have a simple state (whether the nav bar is open and burger has been pressed to open it or not).... if it is open the rest of the background stuff (homepage) becomes a dark color to faded opacity by using conditional rendering-->open?'dark':'light'
i can hand the state down but how do i pass the function (setOpen) from the hook down or how can i change the state from a child component if the state and hook is created in the above parent component (App)
i swear react makes state management silly AF sometime to me

Resources