I have a fixed sidebar. But the right pane has to be split. I used below code segment for that. But the left part of the splitter always stick to the left margin of the page (i.e. sidebar's left margin and split left pane's margin are at the same position). I want to set the left margin of the left pane where the sidebar's right margin is.
<div className="flex">
<Sidebar />
<SplitPane
split="vertical"
minSize={256}
defaultSize={500}
onChange={(size) => persistSplitterPos(size)}
>
<div className="w-full h-page">gggg</div>
<div className="w-full h-page">sss</div>
</SplitPane>
</div>
Sidebar.jsx:
<div class="w-64">
</div>
I tried experimenting with minSize and maxSize. But I couldn't get the desired result.
Here is the codesandbox link.
<SplitPane> that you use, is positioned absolutely, hardcoding left and right style properties to 0px, so by default it attaches itself to the left and right edge of the page and occupies the whole width. In order to gain more control over where the SplitPane gets attached you have to place it in the relatively positioned parent, then absolute positioning of the pane will work in the context of that parent instead of the whole page:
/*styles.css*/
.App {
font-family: sans-serif;
text-align: center;
display: flex;
}
/*App.js*/
<div className="App">
<div
style={{
width: 256,
backgroundColor: "#d5f5cf"
}}
>
Sidebar
</div>
<div
style={{
position: "relative",
width: "100%"
}}
>
<SplitPane>
<div style={{ backgroundColor: "#d5f5cf" }}>Left-Pane</div>
<div style={{ backgroundColor: "#f4edba" }}>Right-Pane</div>
</SplitPane>
</div>
</div>
Related
In my Vue application, I have a navigation drawer that contains a sticky header and content underneath it.
The content is quite long and I'd like to display a divider or a border between the header and the content.
I know a border-bottom on the "sticky-header" div would do it but I want to apply a bottom border to the header only when it becomes stuck (fixed at the top) not when the header is in the default form (relative position).
Below is my code-
<v-navigation-drawer
v-if="drawerNodeData"
class="nav-drawer"
width="408px"
dark
color=#212121
v-model="drawerNode"
absolute
temporary
>
<div class="node-drawer">
<div class="sticky_header">
<div class="close-actor-panel">
<span></span> <!-- To stick the close icon to the right -->
<v-btn icon size="0.8em" #click.stop="drawerNode = false">
<v-icon>mdi-close</v-icon>
</v-btn>
</div>
<v-list-item class="title-and-nb-of-news">
<span v-if="this.drawerNodeData" class="node-title">{{
this.drawerNodeData.id.replaceAll("_", " ")
}}</span>
<div class="chip-for-news">
<DrawerNewsModale
:actorName.sync="actorName"
:filteredNews.sync="filteredNews"
></DrawerNewsModale>
</div>
</v-list-item>
</div>
<div class="content"></div>
</div>
</v-navigation-drawer>
Any idea how to detect if element is sticky or not so I can toggle the border accordingly?
The IntersectionObserver interface of the Intersection Observer API
provides a way to asynchronously observe changes in the intersection
of a target element with an ancestor element or with a top-level
document's viewport.
So, A few lines of IntersectionObserver in JavaScript and tricky usage of top: -1px in the CSS could help to achieve this.
The Below code is containing a header and some content. When the page will be scrolled and the header will be stuck at the top, a bottom border will be applied to the header and when the header is not sticky anymore, the border class will be removed.
const el = document.querySelector(".sticky-element")
const observer = new IntersectionObserver(
([e]) => e.target.classList.toggle("threshold-reached", e.intersectionRatio < 1),
{ threshold: [1] }
);
observer.observe(el);
#parent {
height: 2000px;
}
.sticky-element {
position: sticky;
top: -1px;
z-index: 1;
background: yellow;
}
/* styles for when the header is in sticky mode */
.sticky-element.threshold-reached {
border-bottom: 1px solid black;
}
<div id="parent">
<br />
<div class="sticky-element">Header</div>
<div>Content</div>
<div>Content</div>
<div>Content</div>
<div>Content</div>
<div>Content</div>
<div>Content</div>
<div>Content</div>
</div>
Important- Read more about how this intersection API works.
This question already has answers here:
Why don't flex items shrink past content size?
(5 answers)
Break long word with CSS
(6 answers)
Closed 6 months ago.
I have 3 flex items here, but the width of 2nd item is larger than others, since the description of 2nd item is very long.
Is it possible to make all flex items to have equal height and width but not using fixed value of height and weight, when the content of description changes.
App.js
import "./styles.css";
export default function App() {
const containerStyles = {
display: "flex",
flexDirection: "column",
backgroundColor: "green",
marginRight: "10px",
flex: 1
};
return (
<div style={{ display: "flex" }}>
<div style={containerStyles}>
<div>Title 1</div>
<div>Description 1</div>
<div>Click to view detail</div>
</div>
<div style={containerStyles}>
<div>Title 2</div>
<div>Description 2 veryyyy longgggggggggggggggggggggg</div>
<div>Click to view detail</div>
</div>
<div style={containerStyles}>
<div>Title 3</div>
<div>Description 3</div>
<div>Click to view detail</div>
</div>
</div>
);
}
Codesandbox
https://codesandbox.io/s/crazy-cookies-nw0ykj
The middle box is big because of a unbreakable word longgggggg.... If you overflow it to the next line, things are going to work fine for you.
Setting the overflow-wrap property to anywhere should work.
Try setting it for the flex container
const containerStyles = {
display: "flex",
flexDirection: "column",
backgroundColor: "green",
marginRight: "10px",
flex: 1,
overflowWrap: 'anywhere',
};
So you can see the text being cut in order to respect the width of the container so that you have equal width and height.
Your long word is what's breaking it. You need to set overflow to anything other than visible. You can also add in the word-wrap property to keep everything visible.
const containerStyles = {
display: "flex",
flexDirection: "column",
backgroundColor: "green",
marginRight: "10px",
flex: 1,
"word-wrap": "break-word",
overflow: "hidden"
};
Since I forgot you need the same width as well, I've modified my answer.
In your case, use both justify-content: space-between to made the child element height inside flexbox looks like equal, and overflow-wrap: anywhere to let the longer text to be wrapped to made flex items have same width.
I am trying to move a div from left to right slowly as the user scrolls down. It should stay within it's section and doesn't have to move back to the left when you scroll up.
I am wondering how to do this without using any external package. This is what I have so far but the circle ends up scrolling off the page and I need it to stay on the right hand side once it has gotten there.
<div className="App">
<div className="sectionOne">
<div className="circle styles" style={{ position: 'absolute', left: `${position}rem` }}></div>
</div>
<div className="sectionTwo"></div>
</div>
const [position, setPosition] = useState('70')
function moveCircle() {
const speed = 5
const scrolltop = window.pageYOffset
const scrollAndSpeed = scrolltop / speed
console.log(scrollAndSpeed.toString())
setPosition(scrollAndSpeed.toString())
}
useEffect(() => {
window.addEventListener(
'scroll',
function () {
requestAnimationFrame(moveCircle)
},
false
)
}, [])
I just noticed that you are using rem for the positioning.
So the Math.min would not work for this scenario. You can use the css clamp function.
style={{ position: 'absolute', left: `clamp(0vw, ${position}rem, 100vw - 1rem)` }}
Note that the 1rem i have put in there, should be the width of the .circle element.
I have a React Component with an absolute positioned div which overlays other content in my application. The div is used to fire react's onMouseMove event.
I want to set the css value pointer-events-none so all components underneath the div are still clickable, have pointer events etc. Whatever when pointer-events-none is present, the onMouseMove event will not fire anymore. Everything should behave like the overlay div is not present, it should just fire onMouseMove.
The code structure looks like this:
<button>I should be clickable</button>
<div>
<div
style={{
opacity: 0,
position: `absolute`,
top: `50px`,
left: `50px`,
width: `30vw`,
height: `30vh`,
pointerEvents: `none`,
}}
onMouseMove={() => {
console.log(`Fire!`)
}}
>
Overlay
</div>
<button>I should be clickable</button>
<a>I should be clickabel</a>
</div>
<button>I should be clickable</button>
I think I'm missing something or have chosen a completely wrong path here.
Thanks a lot for your help!
You need to place overlay div at the root (in such case events will propagate), remove pointerEvents rule and opacity so that the content inside div would be visible:
<div
style={{
position: `absolute`,
top: `50px`,
left: `50px`,
width: `30vw`,
height: `30vh`
}}
onMouseMove={() => {
console.log(`Fire!`)
}}
>
<button>I should be clickable</button>
<button>I should be clickable</button>
<a>I should be clickable</a>
<button>I should be clickable</button>
</div>
I'd like to put two elements next to each other but at least one of them (the textarea) I need to have always 100% height of the window. I've checked a few similar questions here but I don't know how to put that together. Could you help?
html:
<div style={styles.rowEqHeight}>
<div style={styles.component}>
<div className='input-group'>
<textarea id='textarea'
className='form-control'
onChange={this.onDataChange}
placeholder='Type your data...'></textarea>
</div>
</div>
<div style={styles.component}>
<Treebeard data={this.state}
decorators={decorators}
onToggle={this.onToggle}/>
</div>
styles.js
export default {
component: {
width: '50%',
display: 'inline-block',
verticalAlign: 'top',
padding: '20px',
},
rowEqHeight: {
display: '-webkit-box',
display: '-webkit-flex',
display: '-ms-flexbox',
display: 'flex'
}
};
try using 100vh in your CSS or inline css for your element. That will set the height to 100% of the window .
sample below:
<textarea style="height:100vh"></textarea>
<textarea id='textarea'
className='form-control'
onChange={this.onDataChange}
placeholder='Type your data...'
style="height: 100vh"></textarea>
This just demonstrates the styling. You could edit it to include the style in styles.js. The vh unit (abbreviated form of viewport height) is a percentage of the total height of the viewport, as evident from the name.