Netflix kind of carousel ui button recreating divs using getComputedStyle css - javascript

I am trying to recreate netflix kind of carousel ui using this wds tutorial (https://www.youtube.com/watch?v=yq4BeRtUHbk) for movie cast details using Reactjs and running through a problem.
I am fetching data from moviedb database and trying to achieve netflix like carousel effect.
the problem is when i click button for changing the slider index using getComputedStyle in css,
I get entire div recreated again several times.
I Fetch the data in the MovieDetails component and pass it to MovieDetailsPage component
export default function MovieDetails() {
const [MovieDetail, setMovieDetail] = useState([])
const [CastDetails, setCastDetails] = useState([])
const { id } = useParams();
const API_Key = '4ee812b6fb59e5f8fc44beff6b8647ed';
console.log('this is id', id);
useEffect(() => {
getDetail();
getCastDetails();
console.log('main');
}, [id])
const getDetail = useCallback(() => {
fetch(`https://api.themoviedb.org/3/movie/${id}?api_key=${API_Key}&language=en-US`)
.then(res => res.json())
.then(data => {
console.log(data, 'data');
setMovieDetail(data)
})
}, [id])
const getCastDetails = useCallback(() => {
fetch(`https://api.themoviedb.org/3/movie/${id}/credits?api_key=${API_Key}&language=en-
US`)
.then(res => res.json())
.then(data => {
setCastDetails(data.cast)
}
)
console.log('get cast details rendered');
}, [id])
useEffect(() => {
console.log(MovieDetail, 'Moviedetils')
}, [MovieDetail])
return (
<div>
<MoviesDetailsPage {...MovieDetail} CastDetails={CastDetails} API_Key={API_Key} />
</div>
)
}
MovieDetailsPage.jsx
export default function MoviesDetailsPage({ id, poster_path, backdrop_path, API_Key,
CastDetails }) {
const API_image = 'https://image.tmdb.org/t/p/w500/';
document.addEventListener('click', e => {
e.preventDefault();
let handle;
if(e.target.matches(".handle")){
handle = e.target
}else{
handle = e.target.closest(".handle")
}
if(handle != null) onHandleClick(handle)
})
function onHandleClick(handle){
const slider = handle.closest(".MovieCastContainer").querySelector(".slider")
console.log(slider, 'sliderindex')
const sliderIndex = parseInt(getComputedStyle(slider).getPropertyValue("--slider-index"))
if(handle.classList.contains("left-handle")){
slider.style.setProperty("--slider-index", sliderIndex - 1)
}
if(handle.classList.contains("right-handle")){
slider.style.setProperty("--slider-index", sliderIndex + 1)
}
}
const castInfo = CastDetails && CastDetails.map(data => <img src={API_image+data.profile_path}
alt={data.name} />)
console.log(CastDetails, 'Castdetails')
return (
<div className="MovieDetailsPageCont">
<div className='MovieDetailsContainer'>
<div className="headerImg"><img src={API_image + backdrop_path}
alt='backdrop_path' style={{ width: '100%', borderRadius: '10px' }} /></div>
<div className="movieid">{id}</div>
</div>
<div className='MovieCastContainer'>
<button className="handle left-handle">
<div className="text">‹</div>
</button>
<div className='slider'>
{
castInfo ? castInfo : '...Loading'
}
</div>
<button className="handle right-handle">
<div className="text">›</div>
</button>
</div>
</div>
)
}
My css page where change the slider index to transfrom to next set of values
*, *::after, *::before{
box-sizing: border-box;
}
:root{
--slider-padding: 5rem;
}
.MovieCastContainer{
display: flex;
justify-content: center;
overflow: hidden;
}
.slider{
--slider-index: 0;
display: flex;
flex-grow: 1;
margin: 0 .25rem;
transform: translateX(calc(var(--slider-index) * -100%));
transition: transform 250ms ease-in-out;
}
.slider > img {
flex: 0 0 25%;
max-width: 25%;
aspect-ratio: 16 / 9;
padding: .25rem;
border-radius: 1rem;
overflow: hidden;
}
.handle{
border: none;
border-radius: 1rem;
flex-grow: 0;
background-color: rgba(0, 0, 0, .25);
z-index: 10;
margin: .25rem 0;
padding: 0 .5rem;
cursor: pointer;
font-size: 5rem;
display: flex;
align-items: center;
justify-content: center;
color: white;
line-height: 0;
transition: font-size 150ms ease-in-out;
}
.left-handle{
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.right-handle{
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.handle:hover,
.handle:focus {
background-color: rgba(0, 0, 0, .5);
}
.handle:hover .text,
.handle:focus .text{
transform: scale(1.2)
}
Everytime I click next button in ui the I get this
please if you can help out with this any help would be appreciated.

Related

The way to optimize react and Typescript codes

In this case, I used React + TypeScript and ant-design. The following code works perfectly but I want the codes to be summarized as much as possible. This is about starting a site that has 3 pages. For example, how can I write this part (const { id, title, description, background } = splash;) so that I don't need to define (splashs[index].background , splashs[index].title, splashs[index].description) all the time.
Thank you in advance for your cooperation.
.splash {
height: 100vh;
position: relative;
overflow: hidden;
}
.bg {
background-color: var(--cjp);
}
.BgGradiant {
background: linear-gradient(107.78deg, rgba(80, 21, 100, 0) 1.87%, rgba(80, 21, 100, 0.05) 18.6%, rgba(80, 21, 100, 0.51) 25.79%, #1C3396 99.02%, #1C3396 51.08%);
}
.context{
width: 80%;
}
.content {
text-align: center;
}
.content h1,
.content p {
color: var(--cwh);
}
.backgroundImage>img {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: -1;
-o-object-fit: cover;
object-fit: cover;
}
.logo {
width: 100%;
text-align: center;
}
.btns {
display: flex !important;
align-items: center;
justify-content: space-between;
-webkit-margin-start: auto;
margin-inline-start: auto;
-webkit-margin-end: auto;
margin-inline-end: auto;
-webkit-margin-before: 2rem;
margin-block-start: 7rem;
}
.btns :global(.ant-btn){
background-color: var(--cwh);
border-radius: var(--borderRadius12);
position: relative;
padding: 4px 10px !important;
}
.btns :global(.ant-btn)::after{
content: "";
position: absolute;
width: 125%;
height: 125%;
top: 50%;
left: 50%;
border: 1px solid var(--chb);
border-radius: var(--borderRadius14);
transform: translate(-50%, -50%);
}
.btns :global(.ant-btn > span){
margin-left: 0 !important;
}
.btns :global(.ant-btn > span > svg){
fill: var(--cal);
}
.btnSkip {
background-color: unset;
outline: none;
border: none;
color: var(--cca);
}
.btnLogin{
-webkit-margin-before: 2rem;
margin-block-start: 7rem;
}
.btnLogin :global(.ant-btn){
border-radius: var(--borderRadius10);
background-color: var(--cwh);
color: var(--cjp);
}
.btnLogin :global(.ant-btn > span){
font-family: "Display-Bold";
}
.dots {
position: absolute;
bottom: 17%;
display: flex !important;
align-items: center;
justify-content: center;
left: 50%;
transform: translateX(-50%);
}
.dot {
width: 10px;
height: 10px;
border-radius: 50%;
}
.dotActive {
background-color: var(--cwh);
}
.dotDeActive {
background-color: var(--cca);
}
.dot:not(:last-child) {
-webkit-margin-end: 0.5rem;
margin-inline-end: 0.5rem;
}
.contentInner{
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
-webkit-padding-before: 2rem;
padding-block-start: 2rem;
-webkit-padding-after: 3rem;
padding-block-end: 3rem;
}
.contentInner1{
justify-content: space-between;
}
.contentInner2{
justify-content: flex-end;
}
import React, { useState } from 'react';
import { useNavigate } from "react-router-dom";
import { Row, Col, Button } from 'antd';
import { ArrowRightOutlined } from '#ant-design/icons';
import Container from '../../Components/UI/Container/Container'
import classes from './Splash.module.css';
import { backgroundSplash1, backgroundSplash2, logoImage } from '../../Assets/index';
const Splash = () => {
let navigate = useNavigate();
const [index, setIndex] = useState<number>(0);
const {
splash,
bg,
BgGradiant,
context,
content,
backgroundImage,
logo,
btns,
btnLogin,
btnSkip,
dots,
dot,
dotActive,
dotDeActive,
contentInner,
contentInner1,
contentInner2,
} = classes
const splashs = [
{
id: 0,
title: 'Page 1 : title 1',
desctiption: '1- Lorem ipsum 1 ',
background: logoImage,
},
{
id: 1,
title: 'Page 2 : title 2',
desctiption: '2- Lorem ipsum 2 ',
background: backgroundSplash1,
},
{
id: 2,
title: 'Page 3 : title3',
desctiption: '3- Lorem ipsum 3',
background: backgroundSplash2,
}
];
const nextBnt = () => {
setIndex(index + 1);
if (index === splashs.length - 1) {
return navigate("/login");
}
}
const skipBtn = () => {
console.log('skip ');
return navigate("/login");
}
const loginBtn = () => {
return navigate("/login");
}
return (
<>
<Row>
<Col xs={24}>
<section
className={`${index === 0 ? bg : BgGradiant} ${splash}`}>
{
splashs.map((splash) => {
const { id, title, desctiption, background } = splash;
console.log(title, "title");
return (
<>
{
index !== 0 && (
<div className={backgroundImage}>
<img src={splashs[index].background} />
</div>
)
}
<Container key={id} className={backgroundImage}>
<div className={`${index === 0 ? contentInner1 : contentInner2} ${contentInner}`}>
{
index === 0 && (
<div className={logo}>
<img src={logoImage} alt="logoImage" />
</div>
)
}
<div className={context}>
<div className={content}>
<h1>{splashs[index].title}</h1>
<p>{splashs[index].desctiption}</p>
</div>
{/* BTNS */}
{
index === splashs.length - 1 ? (
<div className={btnLogin}>
<Button block onClick={loginBtn}>Login</Button>
</div>
) : (
<div className={btns}>
<button className={btnSkip} onClick={skipBtn}>skip</button>
<Button onClick={nextBnt}> <ArrowRightOutlined /></Button>
</div>
)
}
</div>
</div>
</Container>
</>
)
})
}
<div className={dots}>
{
Array.from({ length: 3 }).map((item, idx) => {
return (
<div key={idx} className={`${dot} ${index === idx ? dotActive : dotDeActive}`}></div>
)
})
}
</div>
</section>
</Col>
</Row>
</>
)
}
export default Splash;
Just an advice, your question isn't really well formulated so it's hard to understand what are you trying to accomplish. Try to keep the questions clear and remove any redundant code so the community can better understand it.
If I'm assuming correctly that you don't want to use splash[index] then you should change splash[index].title to title, same for the other props.
Since you already destructured the splash object with const { id, title, description, background } = splash; all these will be available.
Another thing here is, .map method returns the item in the array so I don't see the point in you using the index inside the loop to access the item from the array.

Making scrollable div in CSS

I am making React project but I faced error with css.
Is there any possible way to leave parent and child component same and just make scroll on the left side for the div where are shopping items. I tried with overwflow-y: scroll but it just creates scroll and doesn't make scrollable even if I put some random height. There is way I know but unfortunately at the moment I cant find it.
Parent html
const CartModal = () => {
const { totalPrice, totalAmount } = useSelector((state) => state.cart);
return (
<div className={classes["cart-modal"]}>
<div className={classes["cart-modal__navbar"]}></div>
<div className={classes["cart-modal__body"]}>
<div className={classes["body__left-side"]}>
<h1>ORDERS</h1>
<CartModalFoodList />
</div>
<div className={classes["body__right-side"]}>
<div>
<img src={BigCart} />
</div>
<div>
<h2>Total price:</h2>
<h2>{totalPrice}$</h2>
</div>
<div>
<h2>Total amount:</h2>
<h2>{totalAmount}</h2>
</div>
</div>
</div>
</div>
);
};
.cart-modal {
z-index: 100;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 65vw;
height: 75vh;
background-color: var(--main-bg-color);
border-radius: 10px;
box-shadow: 1px 2px 5px;
overflow: hidden;
}
.cart-modal__navbar {
width: 100%;
height: 15vh;
background: radial-gradient(
50% 50% at 50% 50%,
var(--gradient-color-one) 0%,
var(--gradient-color-two) 100%
);
}
.cart-modal__body {
display: flex;
height: 100%;
}
.body__left-side {
height: 100%;
width: 55%;
background-color: white;
padding: 0 3.5%;
}
.body__left-side h1 {
color: var(--strong-yellow);
text-align: center;
border-bottom: 1px solid var(--weak-yellow);
padding-bottom: 2%;
}
.body__right-side {
width: 45%;
height: 100%;
display: flex;
flex-direction: column;
}
.body__right-side div:first-child {
height: 50%;
width: 100%;
}
.body__right-side div:first-child img {
height: 100%;
width: 100%;
}
.body__right-side *:not(:first-child) {
display: flex;
justify-content: space-around;
}
.body__right-side *:not(:first-child) h2 {
font-size: 2vw;
margin: 2.5% 0;
}
Left side div
const MenuList = (props) => {
const page = props.page;
const dispatch = useDispatch();
const foodArray = props.foodList;
const navigate = useNavigate();
const location = useLocation();
const params = useParams();
const [foodList, setFoodList] = useState([]);
useEffect(() => {
setFoodList(formatArray(foodArray));
}, [foodArray]);
const queryPrams = new URLSearchParams(location.search);
const sort = queryPrams.get("sort");
const onNextPageHandler = () => {
dispatch(uiSliceActions.updatePage("forward"));
};
const onPreviousPageHandler = () => {
dispatch(uiSliceActions.updatePage("backward"));
};
const onSortPageHandler = () => {
navigate(
`/menu/${params.foodId ? params.foodId + "/" : ""}?sort=${
sort === "asc" ? "desc" : "asc"
}`
);
let foodListPart = foodList[page];
let foodListSort = foodList;
const sortFoodList = (sort) => {
foodListPart = foodListPart.sort((a, b) =>
sort === "asc" ? a.foodPrice - b.foodPrice : b.foodPrice - a.foodPrice
);
foodListSort[page] = foodListPart;
setFoodList(foodListSort);
};
sort === "asc" ? sortFoodList("asc") : sortFoodList("desc");
};
return (
<Fragment>
<div className={classes["menu-list"]}>
{foodList[page]
? foodList[page].map((foodObj) => (
<MenuItem key={foodObj.id} foodObj={foodObj} />
))
: ""}
</div>
<div className={classes["menu-list__buttons"]}>
{page >= 1 && (
<Button type="button" onClick={onPreviousPageHandler}>
Page {page}
</Button>
)}
<Button
type="button"
onClick={onSortPageHandler}
className={classes["sort-button"]}
>
{sort === "asc" ? `Descending` : `Ascending`}
</Button>
<Button type="button" onClick={onNextPageHandler}>
Page {page + 2}
</Button>
</div>
</Fragment>
);
};
And css for that div
.menu-list {
overflow-y: scroll;
}
Thank you.
Define the height of the div, then add overflow: auto;
You just need to add overflow-y: scroll to "body__left-side" class
.body__left-side {
height: 100%;
width: 55%;
background-color: white;
padding: 0 3.5%;
overflow-y: scroll;
}
just add over-flow: "auto" to cart-modal__body class
I have fixed this issue by correcting .body__left-side
.body__left-side {
height: 100%;
width: 55%;
background-color: white;
padding: 0 3.5%;
overflow-y: scroll;
}
And also by correcting .menu-list
.menu-list {
height: auto;
padding-bottom: 25%;
}
Thanks to everyone for help.

sticky navbar in React

I need to bring the sticky header. When the user scrolls I need to add this sticky header. I've kept offset greater than 200 and added the respective css code. While I am debugging the code offset is printing correctly but by scrolled site is not getting appended. Any one can guide me what I am doing wrong. Below I have added both style and logic. Thanks in advance!
JSX:
import React, { useState, useEffect } from "react"
import "../styles/global.css"
export default function Navbar() {
const [scrolled, setScrolled] = useState(false)
const handleScroll = () => {
const offset = window.scrollY
console.log("OFFSET VALUE", offset)
if (offset > 200) {
setScrolled(true)
} else {
setScrolled(false)
}
}
useEffect(() => {
window.addEventListener("scroll", handleScroll)
})
let x = ["site-header"]
if (scrolled) {
x.push("scrolled")
}
return (
<>
<header className={x.join("")}>
<div className="wrapper site-header__wrapper">
<h2 className="brand">Community Site</h2>
<nav className="nav">
<div className="nav__wrapper">
<Link className="nav__item" to="/Home">
<h3> Home</h3>
</Link>
<Link className="nav__item" to="/Aboutus">
<h3>What are we</h3>
</Link>
<Link className="nav__item " to="/Contactus">
<h3>Contact Us</h3>
</Link>
</div>
</nav>
</div>
</header>
</>
)
}
CSS:
.site-header {
width: 100%;
max-width: 100%;
box-sizing: border-box;
/* position: relative;
overflow: hidden; */
padding: 15px 10px;
background-color: white;
border: 1px white;
transition: all 0.12s ease;
}
.scrolled {
position: sticky;
top: 0;
left: 0;
background-color: red;
}
.site-header__wrapper {
padding-top: 4rem;
padding-bottom: 6rem;
}
#media (min-width: 600px) {
.site-header__wrapper {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 0;
padding-bottom: 15px;
}
}
#media (min-width: 600px) {
.nav__wrapper {
display: flex;
gap: 12px;
align-items: center;
padding-top: 10px;
padding-bottom: 0;
}
}
I ran some tests and I think I know what happen, you have the class x.join("") however I manually added "site-header" and it worked by also adding an inline style
<header
className={site-header'}
style={scrolled ? { opacity: "1" } : { opacity: "0" }}
>
I also modified the site-header by adding position: fixed; top: 0
If you want to achieve the same result by just adding the class, I recommend you to use properties like opacity or transform: translateY() and add some transition to it
You can try this code.
const [scrolling, setScrolling] = useState(false);
const [scrollTop, setScrollTop] = useState(0);
useEffect(() => {
const onScroll = (e) => {
setScrollTop(e.target.documentElement.scrollTop);
if(scrollTop > 200) {
setScrolling(true)
};
};
window.addEventListener("scroll", onScroll);
return () => window.removeEventListener("scroll", onScroll);
}, [scrollTop, scrolling]);

onClick event not working on a React app, not even with arrow functions

I have a modal component that displays some pictures. The modal is triggered when you click on the leading image. The leading image component is the following:
const LeadingImage = ({ handleOpen, photos }) => {
return (
<ImgWrapper>
<PropertyImg onClick={() => handleOpen(0)} src={photos[0]} />
</ImgWrapper>
);
};
export default LeadingImage;
// Style
let ImgWrapper = styled.div`
width: 100%;
pointer-events: auto;
text-align: center;
border-bottom: 1px solid lightgrey;
cursor: pointer;
`;
let PropertyImg = styled.img`
margin: auto;
display: block;
max-height: 500px;
width: 100%;
object-fit: cover;
height: auto;
pointer-events: inherit;
z-index: 999;
cursor: pointer;
`;
The onClick event used to work the first time I wrote this code, but it stopped working out of the blue. Now whenever I click on the PropertyImg, there is no activity in the console. The DOM doesn't detect any click whatsoever. The cursor doesn't turn into a pointer when hovering over the leading image either.
The code for the handleOpen method is the following:
const handleOpen = async index => {
await setShow(true)
setIndex(index)
console.log("Clicked!")
}
Any idea on what may be the root cause of this behaviour?
EDIT:
This is the component where LeadingImage is rendered. It's an abridged version:
const SelectedProperty = ({ propertyList }) => {
// Hooks
const currentUser = useSelector(state => state.user)
const [show, setShow] = useState(false);
const [index, setIndex] = useState(0);
const handleClose = () => setShow(false);
const handleOpen = async index => {
await setShow(true)
setIndex(index)
console.log("Clicked!")
}
const handleSelect = selectedIndex => {
setIndex(selectedIndex)
}
// Route params
let params = useParams()
// Main variables
var currentProperty = propertyList[params.id]
var photos = currentProperty.media.photos
return (
<Wrapper>
<PropertyRow>
<PropertyCol xs={8}>
<LeadingImage handleOpen={handleOpen} photos={photos} />
</PropertyCol>
// More stuff
</PropertyRow>
</Wrapper>
);
};
export default SelectedProperty;
let Wrapper = styled.div`
margin: auto;
width: 100%;
display: flex;
padding: 0;
position: relative;
`;
let PropertyCol = styled(Col)`
padding: 0;
margin: 30px 20px;
margin-left: 70px;
margin-bottom: 50px;
box-shadow: 1px 3px 5px lightgrey;
background-color: white;
border-radius: 5px;
z-index: -10;
`;
let PropertyRow = styled(Row)`
width: 100%;
.modal-content {
width: 900px;
max-width: 90% !important;
}
z-index: -9999;
`;
The problem its in your PropertyRow style - you are setting an index of -9999. So when you click on image, you not really clicking in it but actually on the div parent.
You can check this just commenting the z-index.
let PropertyRow = styled(Row)`
width: 100%;
.modal-content {
width: 900px;
max-width: 90% !important;
}
/* z-index: -9999; */
`;

How to adjust div height by dragging whole bottom border line instead of bottom right corner in react?

I have one react component. I am able to adjust the height by adding resize: vertical;
overflow: auto; in my css file. However, I only can adjust by dragging bottom right corner of the border. Is it possible to change it to whole bottom line? Or any other react api can achieve this?
This is an example of how I adjust the height by dragging bottom right corner.
This is my component.
<div class='map'>
<MyMapComponent
handleChange={this.handleChange}
handleSubmit={this.handleSubmit}
date ={this.state.date}
getMap={this.getMap}
updateStatus = {this.state.updateStatus}
filter={this.state.filter}
filterList={this.state.filterList}
inputProps={{
classes: {
input: classes.multilineColor
}
}}
>
{/*this.getMap()*/}
</MyMapComponent>
</div>
This is my css file.
.map{
border: 2px solid;
padding: 20px;
width: 300px;
resize: vertical;
overflow: auto;
}
I follow this horizontal resize panel example to create a vertical one.
This is my edited resize panel
import React from "react"
import ReactDOM from "react-dom";
import './ResizablePanels.css';
class ResizablePanels extends React.Component {
eventHandler = null
constructor () {
super()
this.state = {
isDragging: false,
panels: [800, 300, 0]
}
}
componentDidMount () {
ReactDOM.findDOMNode(this).addEventListener('mousemove', this.resizePanel)
ReactDOM.findDOMNode(this).addEventListener('mouseup', this.stopResize)
ReactDOM.findDOMNode(this).addEventListener('mouseleave', this.stopResize)
}
startResize = (event, index) => {
this.setState({
isDragging: true,
currentPanel: index,
initialPos: event.clientY
})
}
stopResize = () => {
if (this.state.isDragging) {
console.log(this.state)
this.setState(({panels, currentPanel, delta}) => ({
isDragging: false,
panels: {
...panels,
[currentPanel]: (panels[currentPanel] || 0) - delta,
[currentPanel - 1]: (panels[currentPanel - 1] || 0) + delta
},
delta: 0,
currentPanel: null
}))
console.log(this.state)
}
}
resizePanel = (event) => {
if (this.state.isDragging) {
//console.log(event.clientY +" "+this.state.initialPos);
const delta = event.clientY - this.state.initialPos
this.setState({
delta: delta
})
}
}
render() {
const rest = this.props.children.slice(1);
// console.log(this.props);
return (
<div className="panel-container" onMouseUp={() => this.stopResize()}>
<div className="panel" style={{height: this.state.panels[0]}}>
{this.props.children[0]}
</div>
{[].concat(...rest.map((child, i) => {
return [
<div onMouseDown={(e) => this.startResize(e, i + 1)}
key={"resizer_" + i}
style={this.state.currentPanel === i+1 ? {top: this.state.delta} : {}}
className="resizer"></div>,
<div key={"panel_" + i} className="panel" style={{height: this.state.panels[i + 1]}}>
{child}
</div>
]
}))}
</div>
)
}
}
export default ResizablePanels;
and this is my css file for this panel
#import url('https://fonts.googleapis.com/css?family=Ubuntu');
html {
background: #333;
font-family: sans-serif;
}
h1 {
color: white;
}
.panel-container {
display: flex;
min-height: 100%;
justify-content: center;
flex-direction: column;
text-align: center;
}
.panel {
background: #EEE;
border: 0px solid gray;
padding: 1px;
}
.panel:first-child {
}
.resizer {
height: 8px;
background: darkGray;
position: relative;
cursor: row-resize;
flex-shrink: 0;
-webkit-user-select: none; /* Chrome all / Safari all */
-moz-user-select: none; /* Firefox all */
-ms-user-select: none; /* IE 10+ */
user-select: none; /* Likely future */
}
.resizer::after,
.resizer::before {
content: "";
border-left: 1px solid #333;
position: absolute;
top: 50%;
transform: translateX(-100%);
right: 0;
display: inline-block;
height: 20px;
margin: 0 2px;
}
.resizer::before {
top: 0;
}

Categories

Resources