Dynamic amount of css grid columns - javascript

right now I have a page with a grid of articles and a absolute positioned footer. What I am trying to accomplish, is that the article grid has a dynamic amount of columns, based on your window height, I thought about calculating the distance between the filter bar (above the article grid) and the footer and divide it by each of the height of a article row, but I just can't figure out how to do it.
Does anyone have an idea?
Code:
<FilterBar>
<div role="button" onClick={filterArticles} className="work-filter-container">
<input type="checkbox" className={`${checkedFilter ? 'checked' : ''} work-filter`} />
<p>ALLEEN WERK </p>
</div>
<div>
<p>sorteer op</p>
<button
type="button"
id="buttonrecent"
className={activeRecent ? 'active' : ''}
onClick={orderRecent}
>
recent
</button>
<span>/</span>
<button
type="button"
id="buttona-z"
onClick={orderAlphabetical}
className={activeAlphabetical ? 'active' : ''}
>
A - Z
</button>
</div>
</FilterBar>
<div>
<GridWrapper>
{articlesOrder &&
articlesOrder.map(article => {
const data = article.node;
const date = data._meta?.firstPublicationDate;
const formattedDate = dateTimeService.getDate({ dateTime: date });
return (
<Article key={data._meta.id}>
<Link href={`/articles/${data._meta.uid}`}>
<a>
<span>{formattedDate}</span>
<p>{data.title?.[0]?.text}</p>
</a>
</Link>
</Article>
);
})}
<br />
</GridWrapper>
</div>
<Footer position="absolute" textColor="white" />
CSS:
export const GridWrapper = styled.div`
display: flex;
flex-direction: column;
gap: 1.2rem;
width: fit-content;
padding: 0 2.3rem;
#media (${({ theme }) => theme.respondTo.desktop}) {
width: 100vw;
overflow-x: auto;
white-space: nowrap;
display: grid;
grid-auto-flow: column;
grid-template-rows: repeat(min(5), 1fr);
}
&::-webkit-scrollbar {
display: none;
}
`;
Screenshot of the problem below:
I want the result to be that the columns go till the footer, without having a fixed amount, like a dynamic amount based on the height of the window.

What you can do to solve this problem
First you have to find out the window.innerHeight where one column fits right, then you increase the screen height with your inspect elements, set it to responsive and look at which height two columns fit right, for example if one column fits the best at 500px window.innerHeight and two columns at 530px, then you know every 30px that is added to your innerHeight, the column count has to increase by 1.
First you have to use the React useState to keep track of the column count
const [columnsAmount, setColumnsAmount] = useState();
With all the above information, you can create a for loop that will look similar to this:
useEffect(() => {
let columns = 1;
for (let i = 500; i < window.innerHeight; i += 30) {
columns += 1;
}
setColumnsAmount(columns);
}, []);

Related

Card Height adjusting on Button Click React

How to adjust this one whenever I click "Create Invoice" it will render a spinner with "Creating invoice". However the height of the card is also changing. I want it to be in fixed position
Please check GIF
https://imgur.com/a/ymJSnpy
const Loading = () => {
return (
<div className="loading" style={divStyle}>
<h4>Creating Invoice
<Spinner size="15px" color="#6491c6"/></h4>
</div>
)}```
could you share what are you putting in loading class and divStyle ?
I think you should add height of 40 and center it vertically if it's not centred on one of those classes:
display: flex;
align-items: center;
height: 40px;

ReactJS Change Navbar color based on scroll to section with dynamic height

I just started to use ReactJS. I currently want to change my Navbar color when user scroll to different section. For example, my section one is red and section 2 is green then my section 3 is blue. I want to let the Nav know that once User enter/scroll to section 1 and it will change color to make the color red and for section 2 and section 3 as well.
Right now I used the window.scroll to achieve this function.
const changeBackground = () => {
if(window.scrollY >= 898 && window.scrollY <= 1997){
//section = '1'
setColor('red')
}
else if(window.scrollY >= 1998 && window.scrollY <= 3097) {
//section = '2'
setColor('green')
}
else if(window.scrollY >= 3098) {
//section = '3'
setColor('blue')
}
My Current problem is that my height is fixed so section 1 is between 898 and 1997px.
However I want to set the height to 100vh so that each section fill up the screen, and based the the 100vh, the px will be different depends on the user screen size.
Any thoughts/tips to let the nav know which section it is on right now?
Thanks so much! happy coding.
One possible solution could be by using intersectional observers. They allow us to observe when an element is visible. We can set a threshold which would make sure that it only triggers when given ratio is visible.
You can use the react-intersection-observer hook to check if each section is in view, once they are you can use that state to change navigation bar color.
You can test this out in the following sandbox:
https://codesandbox.io/s/competent-rubin-nhqz6
This code is not production ready, but you should be able to get an idea of how we can use the intersection observer.
import "./styles.css";
import React from "react";
import { useInView } from "react-intersection-observer";
export default function App() {
const [section1Ref, section1InView] = useInView({ threshold: 0.5 });
const [section2Ref, section2InView] = useInView({ threshold: 0.5 });
return (
<div className="App">
<nav
className="NavBar"
style={{
backgroundColor: section1InView
? "red"
: section2InView
? "blue"
: "green"
}}
/>
<div className="Container">
<section className="Section" ref={section1Ref}>
Section 1
</section>
<section className="Section" ref={section2Ref}>
Section 2
</section>
<section className="Section">Section</section>
</div>
</div>
);
}
Style sheet is simply setting the height to be 100vh minus the header height. And it's ensuring that the scroll works as expeted.
.NavBar {
width: 100%;
height: 20px;
background-color: red;
}
.Container {
height: calc(100vh - 20px);
overflow-y: scroll;
}
.Section {
height: calc(100vh - 20px);
border-bottom: 2px solid black;
}

Not sure how to prevent the scrollbar rendering automatically with content in react app

The content is being rendered this way in the browser, along with the scroll
This is how the modal scrolling looks
const [visiblee, setVisiblee] = useState(false);
const showModall = () => {
setVisiblee(true)
};
const handleOKK = e => {
console.log(e);
setVisiblee(false);
}
const handleCancell = e => {
console.log(e);
setVisiblee(false);
};
<Button style={{float: 'right'}} type="primary" onClick={showModall}>
SQLQuery
</Button>
<Modal class="adjust"
visible={visiblee}
onOk={handleOKK}
onCancel={handleCancell}
width={1000}
bodyStyle={{height:1000}}
>
<p>
<p><JSONPretty id="json-pretty" data={response}></JSONPretty></p>
</p>
</Modal>
<StyledDividerr type="vertical"/><JSONPretty id="json-pretty" data={response}></JSONPretty>{renderChart(component)({ ...renderProps, pivotConfig })}
I want to display the sql this way-
this modal is from antd.
I guess I need to format the SQL, maybe? Is there a way to vertical scroll this?
You have to style the div so it has a fixed witdth, fixed height and overflow scroll property.
.test {
border: 1px solid black;
width: 150px;
height: 150px;
overflow-y: scroll; //vertical scorlling
overflow-x: scroll; //horizontal scroll
}
This is a example fiddle: https://jsfiddle.net/Lmecutg3/2/

Divs Reverse scroll with translateY() in react.js

I'm trying to create with React.js a type of scroll like this one: http://spassky-fischer.fr/, where two divs are scrolling in inverse directions. They are using transform: translateY(), and I tried to implement it as well but I don't get where I'm wrong here. Here's the architecture of the projet. The current version is also here: http://noiseless-tendency.surge.sh/
App.js:
ComponentDidMount(){
window.addEventListener("scroll", this.scrollHandler);
}
...
scrollHandler = () => {
this.setState({
scrollPositionY: window.scrollY
})
}
...
render() {
return (
<div className="App">
<MainItemsContainer {...this.state} />
</div>
);
}
MainItemsContainer.js:
render() {
let style_first = {
transform: `translateY(${this.props.scrollPositionY})`,
overflow: "hidden"
}
let style_second = {
transform: `translateY(-${this.props.scrollPositionY})`,
overflow: "hidden"
}
return (
<div className="main_items_container">
<section
style={style_first}
className="main_items_container_child">
<ItemsContainer {...this.props}/>
</section>
<section
style={style_second}
className="main_items_container_child">
<ItemsContainer {...this.props}/>
</section>
</div>
);
}
App.css:
.main_items_container {
width: 100vw;
display: flex;
align-items: center;
justify-content: center;
position: fixed;
}
.main_items_container .main_items_container_child{
width: 50%;
height: 100vh;
overflow: scroll;
}
The sample site you linked actually uses the wheel event rather than the scroll event. It looks like they use this library to accomplish it: https://swiperjs.com/demos/ . My understanding is that the scroll event only fires if there's a scrollbar, which is why your event handler didn't fire.
I've created a Code Sandbox that produces the effect you want in React. It does rely on jQuery to compute the height of the whole element, and to set the initial transformation for the left half. However, those are just convenience methods, and if you don't want jQuery as a dependency, you can find workarounds for those pretty easily.
So you could use hooks and pass a custom css var through inline styling on state change to update your translateY. I have not tested but I hope you get my drift.
let elRef = useRef(null)
let[ height, setHeight] = useState()
use useLayoutEffect hook to add the event listener
useLayoutEffect (()=>{
if(!elRef) return
elRef.current.addEventListener("scroll", setHeight(elRef.current.scrollY));
return elRef.current.removeEventListener("scroll", setHeight());
}, )
and put the ref on you outermost div perhaps , so your outer div would look like
<div className='container' ref={elRef} style{{ --height: height}} >
<div className='columOne' > </div>
<div className='columTwo' > </div>
</div>
in your css (I haven't put all that is required but just showing how you custom css var is used
.container{
display: flex;
flex-direction: row
}
And within that equal sized columns
.columnOne{
transform: `translateY(calc(var(--height) * 1px)`,
overflow: "hidden"
}
.columnTwo{
transform: `translateY(-calc(var(--height) * 1px)`,
overflow: "hidden"
}
Does that help. Let me know if I could be more clear. Or use styled components and pass a prop in to achieve the same result.

Two containers sharing vertical height dynamically

I have two containers which need to share their parent's height, but the second container is added dynamically on demand. There can be a lot of content in both containers so the opportunity to scroll must be given.
I have a working solution for a 50/50 share, but I wonder if it's possible to share the height dynamically.
.wrapper__container {
display: flex;
height: 100%;
max-width: 100%;
flex-wrap: wrap;
align-items: flex-start;
}
.inside__container {
flex: 0 0 100%;
max-width: 100%;
overflow-y: auto;
}
Part of the wrapper component render method:
render() {
const maxHeight = this.state.showDetails ? '50%' : '100%';
const minHeight = this.state.showDetails ? '50%' : '100%';
return (
<div className="wrapper__container">
<Config
itemsGreen={this.state.itemsGreen}
itemsRed={this.state.itemsRed}
changeItemCount={this.changeItemCount}
/>
<Container
itemCount={this.state.itemsGreen}
className="inside__container"
style={{
backgroundColor: 'green',
maxHeight,
minHeight
}}
onClick={this.handleClick}
/>
{this.state.showDetails && <Container
itemCount={this.state.itemsRed}
className="inside__container"
style={{
backgroundColor: 'tomato',
maxHeight,
minHeight
}}
/>}
</div>
)
}
I've setup a codepen, where you can change the count of items to test the behaviour. Click on the green container to show the red one.
At least it would be a good solution to limit the green container to a max-height 50% and let the red container take up the rest. If the green, for example, is only 20% the red can take 80%.
In a perfect world this should be possible without js calculations but if someone has an idea to calculate this (only react/vanilla).
Target browser is IE11.
Edit: Added a new Pen which is broken, but shows the desired flexible behaviour when there are only a few items.
Each time the outer container is rendered, you need to get the height of the container and divide it by two, then apply that number as the height of each of your internal divs. Like so (using jquery):
var $two = $('<div id="two"></div>');
var $three = $('<div id="three"></div>');
$('#container').append($two);
$('#container').append($three);
var h = $('#one').height();
console.log((h/2)-1)
if($('#two').height() < ((h/2)-1)) {
$('#three').height( ( h-$('#two').height() ) - 1 );
} else {
$('#two').height((h/2)-1);
$('#three').height((h/2)-1);
}

Categories

Resources