ScrollWidth return ClientWidth instead the currect value - reactjs

I'm building a slider with React and framer motion. My idea is to subtract scrollWidth with offsetWidth to get the remaining width of the element.
I always get the value of zero (somehow they are equal). I printed the object and I saw that scrollWidth value returns clientWidth instead.
In the object the value of scrollWidth is totaly different and I cant tell why.

I am Creating This Same Project Carousel Slider In Next.js
But I got scrollWidth is Undefined
I dont Know What Happend But..
I got scrollWidth is undefined
enter image description here
import React, { useEffect, useRef, useState } from 'react'
import { motion } from 'framer-motion';
import cardsUser from '../pages/CardsUsers'
const CardCaousel = () => {
const [width,setWidth] = useState(0)
const carousel = useRef()
useEffect(()=>{
setWidth(carousel.current.scrollWidth - carousel.current.offsetWidth)
},[])
return (
<div className="container max-w-full bg-gradient-to-r from-indigo-500 via-purple-500 to-pink-500 p-5 bggradient">
<div className="liveactionscontainer mt-20">
<h1 className='text-center text-white font-extralight text-6xl mt-2 mb-3'>Live Actions </h1>
<p className='font-extralight text-gray-500 text-center'>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Perspiciatis, suscipit repellat
<br/>
inventore dolor quia quos molestias quae vitae? Eveniet nobis, laborum voluptas culpa libero similique.</p>
<div className="myflex flex justify-center" data-aos="fade-right">
<motion.div className="carousel">
<motion.div
drag="X"
dragConstraints={{right:0,left:-width}}
className="inner-carousel"
>
{cardsUser.map((e)=>{
return (
<motion.div className='item' key={e}>
<div className="mycolumn mb-10">
<div class="nft">
<div class='main'>
<img class='tokenImage' src={e.Imgsrc} alt="NFT" />
<h2>{e.name}</h2>
<p class='description'>Lorem, ipsum dolor sit amet consectetur adipisicing elit. </p>
<div class='tokenInfo'>
<div class="price">
<ins>◘</ins>
<p>0.031 ETH</p>
</div>
<div class="duration">
<button>Place bid</button>
</div>
</div>
<hr />
<div class='creator'>
<div class='wrapper'>
<img src={e.profileImg} alt="Creator" />
</div>
<p><ins>Creation of</ins><span className='text-white'> NF</span> </p>
</div>
</div>
</div>
</div>
</motion.div>
);})}
</motion.div>
</motion.div>
</div>
</div>
</div>
)
}
export default CardCaousel

Related

Add transition to accordion with react + tailwind

I tried to copy this code and convert native javascript to React, everything but the transition works (the content suddenly grows but it has no animation)
import { useState } from "react"
import { FaMinus, FaPlus } from "react-icons/fa"
function Accordion({ title, content }: { title: string; content: string }) {
const [expanded, setExpanded] = useState(false)
const toggleExpanded = () => setExpanded((current) => !current)
return (
<div className={`transition hover:bg-indigo-50 ${expanded ? "bg-indigo-50" : "bg-white"}`} onClick={toggleExpanded}>
<div className="accordion-header cursor-pointer transition flex space-x-5 px-5 items-center h-16 select-none">
{expanded ? <FaMinus className="text-indigo-500" /> : <FaPlus className="text-indigo-500" />}
<h3>{title}</h3>
</div>
<div className={`px-5 pt-0 overflow-hidden transition ${expanded ? "max-h-fit" : "max-h-0"}`}>
<p className="leading-6 font-light pl-9 pb-4 text-justify">{content}</p>
</div>
</div>
)
}
function AccordionWrapper() {
return (
<div className="h-screen bg-gradient-to-br from-pink-50 to-indigo-100 grid place-items-center">
<div className="w-6/12 mx-auto rounded border">
<div className="bg-white p-10 shadow-sm">
<h3 className="text-lg font-medium text-gray-800">Several Windows stacked on each other</h3>
<p className="text-sm font-light text-gray-600 my-3">The accordion is a graphical control element comprising a vertically stacked list of items such as labels or thumbnails</p>
<div className="h-1 w-full mx-auto border-b my-5"></div>
<Accordion title="What is term?" content="Our asked sex point her she seems. New plenty she horses parish design you. Stuff sight equal of my woody. Him children bringing goodness suitable she entirely put far daughter." />
</div>
</div>
</div>
)
}
You need more styles that just transition, you will need to add overflow-hidden transition-[max-height] duration-500 ease-in to the div that you want to change it's max-height
Also as explained in this question you can't use max-h-fit, you will need to set a value for it max-h-40
const { useState } = React
const minusIcon = '-'
const plusIcon = '+'
function Accordion({ title, content }) {
const [expanded, setExpanded] = useState(false)
const toggleExpanded = () => setExpanded((current) => !current)
return (
<div className="my-2 sm:my-4 md:my-6 shadow-sm cursor-pointer bg-white" onClick={toggleExpanded}>
<div className="px-6 text-left items-center h-20 select-none flex justify-between flex-row">
<h5 className="flex-1">
{title}
</h5>
<div className="flex-none pl-2">{expanded ? minusIcon : plusIcon}</div>
</div>
<div className={`px-6 pt-0 overflow-hidden transition-[max-height] duration-500 ease-in ${expanded ? "max-h-40" : "max-h-0"}`}>
<p className="pb-4 text-left">
{content}
</p>
</div>
</div>
)
}
const lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
ReactDOM.createRoot(
document.getElementById("root")
).render(
<div className='py-16 md:py-20 lg:py-24 px-4 bg-black'>
<section className="max-w-6xl mx-auto text-center">
<Accordion title="Accordion #1" content={lorem} />
<Accordion title="Accordion #2" content={lorem} />
<Accordion title="Accordion #3" content={lorem} />
</section>
</div>
);
<div id="root"></div>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/react#18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom#18/umd/react-dom.development.js" crossorigin></script>
When you use transition class only that properties transition when they change:
color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter
You should use transition-all class instead of transition.
tailwind docs

TailwindCSS: How can I fix a header & footer to the screen while keeping scrollable content in between?

I'm creating a React PWA for a client using Tailwind CSS and I want to achieve a layout in which there's a header fixed to the top of the screen and a navbar fixed to the bottom of the screen. In between I'll display scrollable content of dynamic size.
I've been struggling with this problem for the most part of the day and I'm following the instructions on this answer as well as the code it provided here.
I though I got it, as I implemented all the recommended classes in the relevant components and I got this result on my browser dev tools:
However, I got curious and decided to open the page on my phone. This is the result there and, as you can see, neither of the desired elements are actually fixed to the screen:
At this point I'm completely lost. I've tried using className={fixed} in the Navbar, but it ends up clipping part of the content even when adding margin or padding to either the navbar or the content.
How can I fix both header and navbar to the screen while keeping the content scrollable?
These are the relevant parts of my code:
App.js:
function App() {
return (
<Router>
<div className='flex flex-col h-screen overflow-hidden'>
<Header></Header>
<div className='MainContent flex-1 overflow-y-scroll py-2 mx-2'>
<Routes>
<Route path="/" element={<OrderView />} />
<Route path="/DeliverymenView" element={<DeliverymenView />} />
<Route path="/InventoryView" element={<InventoryView />} />
<Route path="/RouteGenerationView" element={<RouteGenerationView />} />
<Route path="/AdministrativeView" element={<AdministrativeView />} />
<Route path="*" element={<ErrorView />} />
</Routes>
</div>
<Navbar></Navbar>
</div>
</Router>
);
}
Header.js:
const Header = () => {
return (
<div className="Header shadow-md bg-white w-full ">
<CurrentPage />
</div>
)
}
Navbar.js:
function Navbar() {
return (
<div className="Navbar w-full flex flex-row gap-x-2 justify-evenly py-1 bg-white drop-shadow-md-top">
<Link to="/">
<MdShoppingCart className="text-zinc-400 text-5xl "></MdShoppingCart>
</Link>
<Link to="/DeliverymenView">
<MdPerson className="text-zinc-400 text-5xl "></MdPerson>
</Link>
<Link to="/InventoryView">
<MdViewList className="text-zinc-400 text-5xl "></MdViewList>
</Link>
<Link to="/RouteGenerationView">
<MdDeliveryDining className="text-zinc-400 text-5xl "></MdDeliveryDining>
</Link>
</div>
)
}
One way to keep flex on the parent container is to add sticky to the header and footer divs, with top-0 or bottom-0, like this:
Modified code from the tailwind play linked in your question.
<div class="flex flex-col h-screen">
<header class="w-full text-center border-b border-grey p-4 sticky top-0">Some header</header>
<main class="flex-1 overflow-y-scroll">
<div class="min-h-screen bg-slate-100">
<p>This is a very long section that consumes 100% viewport height!</p>
</div>
<div class="min-h-screen bg-slate-200">
<p>This is second long section that consumes 100% viewport height!</p>
</div>
<div class="min-h-screen bg-slate-100">
<p>This is third long section that consumes 100% viewport height!</p>
</div>
<div class="min-h-screen bg-slate-200">
<p>This is fourth long section that consumes 100% viewport height!</p>
</div>
<div class="min-h-screen bg-slate-100">
<p>This is fifth long section that consumes 100% viewport height!</p>
</div>
</main>
<footer class="w-full text-center border-t border-grey p-4 sticky bottom-0">some footer</footer>
</div>
Actually you don't need to set the position to "fixed" or "absolut". The problem can be solved simpler.
You need 4 divs. One as a container (we can call its class "root") which contains the further 3 divs.
For defining how much space each inner div can take from the root div we can use "flex" (with "flex" you can define the proportion to other components).
(You can of course change height and width of root as you like)
.root {
height: 70vh;
width: 50vw;
display: flex;
flex-direction: column;
justify-content: stretch;
}
.Header--container {
flex: 1;
background-color: green;
}
.Footer--container {
flex: 1;
background-color: red;
}
.Content--container {
flex: 5;
background-color: white;
overflow-y: scroll;
}
<div class="root">
<div class="Header--container">
</div>
<div class="Content--container">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata
sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
</div>
<div class="Footer--container">
</div>
</div>

Dropdown doesn't work in a loop but normal

I am making a dropdown accordion. After adapting my code to the example bellow, everything works fine:
Example: https://codepen.io/CreativeBulma/pen/YbQqoQ
trainingData
[{
"von": "17:00",
"bis": "18:00",
"tag": "Mittwoch",
"trainingsid": 46
},
{
"von": "19:00",
"bis": "21:00",
"tag": "Donnerstag",
"trainingsid": 51
}]
That's how it works:
<div ref={collapsiblesRef} id={`accordion_first2`}>
<div className="card">
<header className="card-header">
<p className="card-header-title">
montaj
</p>
<a href={`#collapsible-card-0`} data-action="collapse" className="card-header-icon is-hidden-fullscreen" aria-label="more options">
<span className="icon">
<i className="fas fa-angle-down" aria-hidden="true"></i>
</span>
</a>
</header>
<div id={`collapsible-card-0`} className="is-collapsible" data-parent={`accordion_first2`}>
<div className="card-content">
<p className="is-small has-text-primary has-text-weight-semibold">Tag</p>
<input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Wochentag" />
<p className="is-small has-text-primary has-text-weight-semibold">Uhrzeit von</p>
<input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Uhrzeit von" />
<p className="is-small has-text-primary has-text-weight-semibold">Uhrzeit bis</p>
<input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Uhrzeit bis" />
<article className="message mt-3">
<div className="message-body">
Uhrzeit von ist die Startzeit und Uhrzeit bis ist die Endzeit des Trainings. Gültiges Format hh:mm, z.B. 17:45.
</div>
</article>
</div>
</div>
</div>
<div className="card">
<header className="card-header">
<p className="card-header-title">
dasdasd
</p>
<a href={`#collapsible-card-1`} data-action="collapse" className="card-header-icon is-hidden-fullscreen" aria-label="more options">
<span className="icon">
<i className="fas fa-angle-down" aria-hidden="true"></i>
</span>
</a>
</header>
<div id={`collapsible-card-1`} className="is-collapsible" data-parent={`accordion_first2`}>
<div className="card-content">
<p className="is-small has-text-primary has-text-weight-semibold">Tag</p>
<input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Wochentag" />
<p className="is-small has-text-primary has-text-weight-semibold">Uhrzeit von</p>
<input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Uhrzeit von" />
<p className="is-small has-text-primary has-text-weight-semibold">Uhrzeit bis</p>
<input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Uhrzeit bis" />
<article className="message mt-3">
<div className="message-body">
Uhrzeit von ist die Startzeit und Uhrzeit bis ist die Endzeit des Trainings. Gültiges Format hh:mm, z.B. 17:45.
</div>
</article>
</div>
</div>
</div>
</div>
Since I am having several elements I want to add to the dropdown, I am using a loop. But unfortunately, after adding the loop, the collapsibles aren't working properly - they are staying open and I cannot close them or interact with them.
So that's actually what I want:
<div ref={collapsiblesRef} id={`accordion_first`}>
{trainingData.map((d, i) => (
<div className="card" key={i}>
<header className="card-header">
<p className="card-header-title">
{d.tag}
</p>
<a href={`#collapsible-card-${i}`} data-action="collapse" className="card-header-icon is-hidden-fullscreen" aria-label="more options">
<span className="icon">
<i className="fas fa-angle-down" aria-hidden="true"></i>
</span>
</a>
</header>
<div id={`collapsible-card-${i}`} className="is-collapsible" data-parent={`accordion_first`}>
<div className="card-content">
<p className="is-small has-text-primary has-text-weight-semibold">Tag</p>
</div>*/}
<input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Wochentag" />
<p className="is-small has-text-primary has-text-weight-semibold">Uhrzeit von</p>
<input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Uhrzeit von" />
<p className="is-small has-text-primary has-text-weight-semibold">Uhrzeit bis</p>
<input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Uhrzeit bis" />
<article className="message mt-3">
<div className="message-body">
Uhrzeit von ist die Startzeit und Uhrzeit bis ist die Endzeit des Trainings. Gültiges Format hh:mm, z.B. 17:45.
</div>
</article>
</div>
</div>
</div>
))}
</div>
I played a bit with the code, this works for me.
import React from "react";
import bulmaCollapsible from '#creativebulma/bulma-collapsible';
import 'bulma';
import '#creativebulma/bulma-collapsible';
///I want to generate a random number of collapsibles.
const array = [0,1,2,3,4,5,6]
class Collapsibles extends React.Component {
componentDidMount() {
this.collapsibles = bulmaCollapsible.attach(".is-collapsible", {
container: this.refs.collapsibles
});
}
render() {
const collapsibles = array.map((c,i) => <article className="message">
<div className="message-header">
<p>
Question 1{" "}
<a href={"#collapsible-message-accordion-"+ i.toString()} data-action="collapse">
Collapse/Expand
</a>
</p>
</div>
<div
id={"collapsible-message-accordion-"+ i.toString()}
className="message-body is-collapsible is-active"
data-parent="accordion_first"
>
<div className="message-body-content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.{" "}
<strong>Pellentesque risus mi</strong>, tempus quis placerat ut,
porta nec nulla. Vestibulum rhoncus ac ex sit amet fringilla.
Nullam gravida purus diam, et dictum
<a>felis venenatis</a> efficitur. Aenean ac{" "}
<em>eleifend lacus</em>, in mollis lectus. Donec sodales, arcu et
sollicitudin porttitor, tortor urna tempor ligula, id porttitor mi
magna a neque. Donec dui urna, vehicula et sem eget, facilisis
sodales sem.
</div>
</div>
</article>)
return (
<div ref="collapsibles" id="accordion_first">
{collapsibles}
</div>
)
}
}
export default Collapsibles
A few notes on the code:
First, I assume you're aware that bulmaCollapsible is an npm package that needs to be installed. You can find directions for installation here.
I didn't fully understand where you got your code from, I copied mine from the CodePen you provided. Each collapsible container is an article tag.
My code lacks any transition properties. So it won't slowly open and close. You'll have to add some minor css to make that happen.
The method attach is responsible to initialise any element with the className of is-collapsible. It was made so you can initialise multiple collapsibles at once.
In my code I created an array const called "array". Then I used the map method like you did to generate multiple collapsibles.
The following will give you 1 collapsible:
<article className="message">
<div className="message-header">
<p>
Question 1{" "}
<a href={"#collapsible-message-accordion-"+ i.toString()} data-action="collapse">
Collapse/Expand
</a>
</p>
</div>
<div
id={"collapsible-message-accordion-"+ i.toString()}
className="message-body is-collapsible is-active"
data-parent="accordion_first"
>
<div className="message-body-content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.{" "}
<strong>Pellentesque risus mi</strong>, tempus quis placerat ut,
porta nec nulla. Vestibulum rhoncus ac ex sit amet fringilla.
Nullam gravida purus diam, et dictum
<a>felis venenatis</a> efficitur. Aenean ac{" "}
<em>eleifend lacus</em>, in mollis lectus. Donec sodales, arcu et
sollicitudin porttitor, tortor urna tempor ligula, id porttitor mi
magna a neque. Donec dui urna, vehicula et sem eget, facilisis
sodales sem.
</div>
</div>
Each collapsible needs to have a unique id. For each collapsible we use an a tag with an href attribute equal to the collapsible's id. This is reflected in the lines where you see href={"#collapsible-message-accordion-"+ i.toString()} and id={"#collapsible-message-accordion-"+ i.toString()}
To know more about how this package work, visit their JS API page.

tailwind css responsive grid issue

I got issue when trying to add a "screen" prefix to grid-column, the layout is perfect but when I add md: to grid-col-span-6 everything is messed up.
this is the code :
import React from "react";
import app from "../images/app.png";
const Featured = () => {
return (
<div className="mt-52 ">
<h1 className="text-primary-dark-theme text-5xl mt-14">Projects</h1>
<div className="grid grid-cols-12 grid-rows-1 mt-20 ">
<div className="row-start-1 row-span-1 col-start-1 md:col-span-6">
<img src={app} alt="" className="w-full" />
</div>
<div className="row-start-1 row-span-1 col-start-6 col-span-7">
<div className="h-full w-full">
<h1 className="text-right text-primary-dark-theme">
Featured Project
</h1>
<h1 className="text-right text-gray-300 font-bold ">Title</h1>
<p className="p-5 bg-gray-800 text-gray-400 shadow-lg rounded-md mt-5">
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Optio id
doloribus sequi repellendus aperiam dolore!
</p>
</div>
</div>
</div>
</div>
);
};
export default Featured;
This is how the ui looks in md
this is the result i want to have
this what happened when i add md predix to col-span-6
The issue seems to be that when applying the responsive md:col-span-6 it also overrides col-start-1 (you can see the styles no longer applied in the dev tools). Adding md:col-start-1 seems to fix this behaviour.
However, simply changing your image's wrapper <div /> to:
<div class="row-start-1 row-span-1 col-start-1 col-span-12">
Seems to have the desired result.

Warning: Received `true` for a non-boolean attribute `uk-grid`

I'm pretty new to React and getting this error when trying to use a https://getuikit.com/docs/card uikit card as a component.
Removing the attribute completely ruins the structure of the cards.
import React from 'react';
import faker from 'faker';
import "./css/Cards.css";
const Cards = (props) => {
return (
<div className="uk-card uk-card-default uk-width-1-2#m">
<div className="uk-card-header">
<div className="uk-grid-small uk-flex-middle" uk-grid>
<div className="uk-width-auto">
<img className="uk-border-circle" width="40" height="40" src={faker.image.animals} />>
</div>
<div className="uk-width-expand">
<h3 className="uk-card-title uk-margin-remove-bottom">Title</h3>
<p className="uk-text-meta uk-margin-remove-top"></p>
</div>
</div>
</div>
<div className="uk-card-body">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt.</p>
</div>
<div className="uk-card-footer">
Read more
</div>
</div>
)
}
export default Cards;
Thanks in advance!
According to the docs at https://getuikit.com/docs/javascript#component-usage when using with React you must prefix the attributes with data-.
So, instead of:
<div className="uk-grid-small uk-flex-middle" uk-grid>
Try:
<div className="uk-grid-small uk-flex-middle" data-uk-grid>

Resources