I have a scrollable div area, I want to detect user to hover on items inside.
I want to group these items and put a handle on hover so I can drag them as a group.
But items needs to be flat in DOM in only .wrap div, even though they are logically grouped together.
What is the best way to detect a handle on mouse hover on these groups?
Finally I want to absolutely position these items when dropped in place.
Obviously I tried getBoundingClientRect, scrollTop, and other stuff to get a normalized mouse coordinate on the target wrapper element.
I think one way would be to strategically place handle divs within the wrapper element and natively detect onMouseOver event, what do you think?
body {
margin: 0;
padding: 0;
}
.ok {
background: #ccc;
position: relative;
width: 100vw;
height: 100vh;
display: flex;
}
.wrap {
background: white;
position: absolute;
top: 0;
left: 0;
height: 30%;
width: 100%;
display: flex;
flex-flow: column;
gap: 0.2em;
overflow-y: auto;
}
.wrap item {
flex-shrink: 0;
background: orange;
padding: 1em;
width: 100%;
height: 4em;
}
<div class='ok'>
<div class='wrap'>
<item> <span> text </span> <span> world </span> </item>
<item>asdf</item>
</div>
</div>
Related
I have a flexbox container with scrolling along the x axis. It scrolls properly, but for some reason, many items within the container are hidden to the left of the screen, outside of the display. I have no idea why and am looking to make it such that the first element in the list is the first element seen in the leftmost box of the flexbox.
.home-carousel-cards {
display: flex;
flex-direction: row;
overflow-x: auto;
flex-shrink: 0;
margin: 0 -1px;
justify-content: center;
}
.home-item-card {
width: 241px;
min-width: 220px;
height: 300px;
background: white;
border-radius: 16px;
cursor: pointer;
margin: 0 1px;
border: 1px solid black;
}
The result:
The blue highlighted div is the first visible element. As you can see, the first shoe actually seen is certainly not the first element in the list, and all of the previous elements are not visible. I want the user to scroll right to the end of the list but can't get past this.
I'm trying to make a short pop up in my web app for when a user clicks on a code to copy it. The trouble I'm having is trying to figure out to make it not shift everything in the parent div.
The gif below is what currently happens after all my attempts and googling of trying to solve this problem. What I'm trying to get to happen is have that copied message bubble just appear to the top right of the span with the room code.
This fiddle is a stripped down version of the interaction. I've tried all the different display and positionings and I'm not really sure where to go from here. Thanks in advance to everyone.
https://jsfiddle.net/k6ey1duc/36/
.container {
background-color: #008afa;
width: fit-content;
margin: auto;
padding: 20px
}
.text {
display: inline;
}
.pop-up {
display: none;
background-color: #fe0c0d;
}
#show-hide {
display: block;
margin: auto;
}
<body>
<script>
$(document).ready(function() {
var x = false;
$('#show-hide').on('click', function() {
if (!x) {
$("#pop-up").css({
"backgroundColor": "#fe0c0d",
"display": "inline"
});
x = true;
} else {
$("#pop-up").hide();
x = false;
}
});
});
</script>
<div class='container'>
<p class='text'>
Hello there! <span>Here is a span.</span>
</p>
<div id='pop-up' class='pop-up'>
Here is a pop-up
</div>
<button id='show-hide'>
Click for pop up
</button>
</div>
</body>
Adding position: absolute; to .pop-up will prevent the container from making any space for the element which is what you are trying to prevent. Additionally, adding position: relative; to .container will give you freedom to position .pop-up anywhere relative to the container.
Another solution is replacing the display: none; display: inline; with visibility: visible; visibility: hidden;. The main difference between these two is that display will remove the entire element from the layout whereas visibility will only hide the element but retain the elements space. This will solve the resizing container problem but will not give you the advantages of stacking and positioning that position: absolute does.
.container {
position: relative;
background-color: #008afa;
width: fit-content;
margin: auto;
padding: 20px
}
.pop-up {
position: absolute;
display: none;
background-color: #fe0c0d;
}
Use position:relative and postion:absolute.
.container {
background-color: #008afa;
width: fit-content;
margin: auto;
padding: 20px;
position: relative;
}
.pop-up {
display: none;
background-color: #fe0c0d;
position: absolute;
left:100%;
width:inherit;
}
I want all 100% height elements to expand when the size of the body expands.
In the example pressing the button will add a red div - the two columns adjacent should stretch to account for this. In the end all columns should reach the bottom completely, one with blue then red, the other two just blue.
I'm looking into flex, and it doesn't seem like this would work, but any suggestions are appreciated.
In any case best solution is CSS, but if this is impossible pure JS is also fine.
span = document.getElementsByTagName("span")[0];
function addelem() {
span.appendChild(document.createElement('div'));
};
html, body{
height: 100%;
}
span {
display: inline-block;
background-color: blue;
width: 30px;
height: 100%;
vertical-align: top;
}
div {
background-color: red;
width: 30px;
height: 30px;
}
<span><span></span></span>
<span></span>
<span><button onclick="return addelem()">+</button></span>
This is what I expect the frame to look like at the bottom after button is pressed and scrolled down:
EDIT
I changed the snippet so the button appends the div to an existing child and causes overflow, as per the comments below suggest.
An initial setting of a flex container is align-items: stretch. This means that flex items will expand to cover the full length of the container along the cross axis.
In a container with flex-direction: row, the cross axis is vertical, so items will expand to full height.
In your demo code, the divs (red) are being added as children of a span column (blue). These divs are being added to the end, forcing the column to grow.
In a row-direction flex container, with no heights specified that would override align-items: stretch, the other columns will follow suit.
span = document.getElementsByTagName("span")[0];
function addelem() {
span.appendChild(document.createElement('div'));
};
body {
display: flex;
min-height: 100vh;
}
body > span {
width: 30px;
margin-right: 5px;
background-color: blue;
display: flex;
flex-direction: column;
}
body > span:first-child span {
flex: 0 0 100vh;
}
div {
background-color: red;
width: 30px;
height: 30px;
}
button {
margin-bottom: auto;
}
<span><span></span></span>
<span></span>
<span><button onclick="return addelem()">+</button></span>
You should use Flexbox twice, once in the outer container, and once in the container containing the appended child elements.
Here is your modified code:
span = document.getElementsByTagName("span")[0];
function addelem() {
span.appendChild(document.createElement('div'));
};
html, body{
height: 100%;
/* new */
display: flex;
}
/* new */
body > span{margin-right: 4px;}
span {
/*display: inline-block;*/
background-color: blue;
width: 30px;
height: 100%;
vertical-align: top;
/* new */
display: flex;
flex-flow: column;
align-items: flex-end;
}
div {
background-color: red;
width: 30px;
height: 30px;
/* new */
flex: 1 0 auto;
}
<span><span></span></span>
<span></span>
<span><button onclick="return addelem()">+</button></span>
I am trying to overlay 2 DIV's in my main parent DIV:
I want to overlay the the second div over on top of the first one. I have a problem overlaying it as I cannot keep it in the middle of the screen.
I have tried this to overlay:
The overlay works fine here, but my container is no longer center when I do this. How can I overlay and keep it center ?
div {
border: 5px solid red;
}
#first {
position: absolute;
z-index: 1;
border-color: orange;
}
#second {
position: absolute;
z-index: 2;
border-color: green;
}
<div id="container" class="container text-center">
<div id="first">Hi</div>
<div id="second">Hello</div>
</div>
Here is what you need to do (see width of both divs and text-align properties):
You can give them background color to see z-index works perfectly :)
#first {
text-align: center;
height: 300px;
width: 100%;
position: absolute;
z-index: 1;
}
#second {
text-align: center;
height: 300px;
width: 100%;
position: absolute;
z-index: 2;
}
<div id="container" class="container text-center">
<div id="first">Hi</div>
<div id="second">Hello</div>
</div>
When you position absolute, the positioned element is taken out of the document flow and positioned relative to the next highest parent element that is not the default position, i.e. not position: static;
The following will cause the absolute positioned children to stay within the containing div:
#container {
position: relative;
}
Your container's text is no longer centered because you have removed its children from the document flow. In essence, it has no content and collapses, and therefore, has no width to which to align the text.
One thing you could do is set the container to position: relative and full-width (i.e. width: 100vw), then set its children to width: 100%.
Then the inner divs will take on the width of their parent.
See this working JSFiddle.
#container {
position: relative;
width: 100%;
height: 100px;
background-color: yellow;
display: flex;
justify-content: center;
align-items: center;
}
#first{
position: absolute;
}
#second{
position: absolute;
}
<div id="container" class="container">
<div id="first">Hi</div>
<div id="second">Hello</div>
</div>
Your main issue is that the divs will not have any relative width to the parent div.
Therefore the text is still technically "centered" in each corresponding div because they're inheriting text-align: center from the container div.
However, the divs' widths will automatically be as wide as they needs to be (i.e. to fit the text, in this case).
You can remedy this one of two ways:
Force the divs to be centered
Give both divs the following (extra) CSS:
left: 50%;
width: 100%;
margin-left: -50%;
This will literally center them in their parent div.
or
Force the divs to be the same size as their parent
Give both the divs the following (extra) CSS:
top: 0;
bottom: 0;
left: 0;
right: 0;
This sets the divs to span their entire parent's height and width.
In both situations, you might need to make the .container class use position: relative, in order for the child divs to have something to be absolute to.
If you're using Bootstrap, there is no need to worry about this, as .container class already has this applied.
Hope one of these solutions helps you :)
Try this style:
#first,
#second {
left: 50%;
transform: translate(-50%, 0);
}
div {
border: 5px solid red;
}
#first {
position: absolute;
z-index: 1;
border-color: orange;
}
#second {
position: absolute;
z-index: 2;
border-color: green;
}
#first,
#second {
left: 50%;
transform: translate(-50%, 0);
}
<div id="container" class="container text-center">
<div id="first">Hi</div>
<div id="second">Hello</div>
</div>
I've spent some time working on a slider that has a div follow the thumb of slider. I did this by creating a relatively positioned container for the follower (called #slider-follower-cntnr). I then adjust the position of the follower div (#slider-follower) according to the value of the range input. The problem is that as you move the thumb across the track the follower does not stay perfectly centered against the position of the thumb. I've tried adjusting the width of the #slider-follower-cntnr but I don't no how to find the correct width to keep it perfectly centered. Thanks for any help.
TL/DR: How can I keep follower div centered perfectly to the thumb of the range input across all range values?
Heres a codepen. You may need to full screen to see it get off center as you pull it along the range.
HTML
<div id="slider-cntnr">
<input type="range" id="frame-slider" oninput="updateFollowerValue(this.value)" />
<div id="slider-follow-cntnr">
<div id="slider-follow">
<div id="slider-val-cntnr">
<span id="slider-val"></span>
</div>
</div>
</div>
</div>
JS
var follower = document.getElementById('slider-follow');
var follower_val = document.getElementById('slider-val');
var slider = document.getElementById('frame-slider');
var updateFollowerValue = function(val) {
follower_val.innerHTML = val;
follower.style.left = (val*1) + '%';
};
updateFollowerValue(slider.value);
CSS
html, body {
width: 100%;
height: 100%;
}
#slider-cntnr {
width: 80%;
margin: 40px;
position: relative;
display: flex;
flex-direction: column;
background: orange;
}
#frame-slider {
width: 100%;
margin: 0;
}
#slider-follow-cntnr {
position: relative;
background-color: blue;
height: 10px;
margin: 0 auto;
width: 98%;
}
#slider-follow {
background-color: black;
width: 30px;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
margin-left: -15px;
}
#slider-val-cntnr {
background-color: white;
width: 25px;
height: 20px;
}
#slider-val {
margin-left: 9px;
}
Few ways you can fix this:
(1) In the HTML
<div id="slider-val-cntnr">
<center>
<span id="slider-val"></span>
</center>
</div>
(2) In the CSS
#slider-val {
margin-left: auto;
margin-right: auto;
}
(1) The HTML method probably works the best, but it's generally not best practice to have <center> tags throughout your HTML.
(2) This will make sure that the number never goes beyond the bounds of the white box that it resides in. If you don't care that it is absolutely centered, and just want the number to not exit the box, then this is a suitable solution.