Shadow under fixed header upon scrolling - html

I am creating a website and I want shadow under my fixed header upon scrolling.
This means when the site loads there is no shadow under the header but when I scroll the page the shadow should appear below the header.
Here is my css code
EDIT : I am using reactjs for rendering the header
.nav-heading {
background-color: $white;
top: 0;
display: flex;
flex-direction: row;
position: fixed;
width: 100%;
z-index: 1;
// margin-top: 1.25rem;
}
.nav-heading::after {
position: fixed;
box-shadow: 0px 0px 6px 0px rgba(0, 0, 0, 0.7);
}

You could use JQuery, that is a javascript lib.
First you need to install JQuery.
One easy way is by CDN.
<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
Then add your script like this.
<script>
$(window).scroll(function(){
$(".nav-heading").css("box-shadow","here insert the value you want for the box-shadow")
})
</script>
If you want to the shadow fade out after scrolling you can use:
<script>
$(window).scroll(function(){
$(".nav-heading").css("box-shadow","here insert the value you want for the box-shadow").fadeOut( "slow" );
})
</script>
You can access more about in:
https://code.jquery.com/
Edit: How Using React.js
You can create functions to deal with the state of scrolled or not.
constructor() {
super();
this.state = {
className: 'notShadow'
}
}
handleScroll() {
if (document.documentElement.scrollTop > 430) {
this.setState({
className: 'withShadow'
})
}
}
componentDidMount() {
window.onscroll = () => this.handleScroll()
}
And then inside your header you can call the state as class.
<Nav className={this.state.className} />
If you don't know the number of pixels you can use:
console.log(document.documentElement.scrollTop);

Related

hide element on scroll within div vuejs3

I'm trying to make an element hide on scroll within a div. I tried this tutorial https://codepen.io/neutraltone/pen/poobdgv, but it works when the complete window is scrolled. I could not make it work on the specific div.
mounted() {
this.lastScrollPosition = window.pageYOffset
window.addEventListener('scroll', this.onScroll)
},
beforeUnmount() {
window.removeEventListener('scroll', this.onScroll)
},
I'm using Vuejs 3. I think the problem is, that I can't specifically point to the div. I tried it with this.$ref.name (using ref="name" on the div), instead of window, but something is not adding up.
Thanks in advance!
You could listen for the scroll event on the div using the v-on:scroll listener (or shorthand (#scroll) and then do whatever you want in the handler (in this case checking for scroll position and then hiding the element):
<template>
<div class="scrollable-container" #scroll="scrollHandler">
<div class="content">
<div v-show="isVisible" class="to-hide">Scroll Me</div>
</div>
</div>
</template>
<script>
export default {
data: function() {
return {
isVisible: true
};
},
methods: {
scrollHandler(e) {
this.isVisible = e.target.scrollTop > 300 ? false : true
}
}
}
</script>
<style>
.scrollable-container {
height: 500px;
width: 300px;
margin: 200px auto;
overflow-y: scroll;
border: 1px solid black;
}
.content {
height: 1000px;
}
.to-hide {
min-height: 500px;
background-color: blue;
}
</style>

Vue.js: do not show element until it is in correct position

I am learning Vue and really enjoying it. I have a tab that I want fixed to the bottom of the browser window when the page loads. When a user clicks the tab, it will slide up to show some content.
Everything is working great. I am able to have the tab stick to the bottom of the page - and click events are working great as well.
The problem I am having is that I need to calculate the height of tab (and div) to set the CSS property correctly. When the page loads, you can see the tab slide down into place. I would like to hide the tab until everything has been calculated and it's in the correct place.
Here is what I'm using:
app.js
new Vue({
el: '#info',
delimiters: ['${', '}'],
data: {
active: false,
inactive: true,
styles: {
'bottom': 0
},
},
methods() {
toggle: function (event) {
event.preventDefault();
this.active = !this.active;
this.inactive = !this.inactive;
}
},
mounted() {
let tabHeight = this.$refs.infoTab.clientHeight;
let boxHeight = this.$refs.infoBox.clientHeight; // 473px
this.styles.bottom = -boxHeight + 'px';
}
});
HTML
<div class="info not-active" id="info" #click="toggle" ref="infoTab"
v-cloak
v-bind:class="{ active: active }"
v-bind:style="styles">
<!-- content -->
</div>
style.css
[v-cloak] {
display: none;
}
/* more classes */
.info {
width: 100%;
position: fixed;
&.inactive {
bottom: -100%;
}
&.active {
bottom: 0 !important;
}
}
I know I am close, I just don't want users to see the tab slide into place. It should just be there. I tried using the created hook, but clientHeight is not available.
Any suggestions are greatly appreciated!
I think you can solve this just using CSS, no need to use any of Vue's lifecycle hooks, I made a pen with a vanilla JS example:
let infoNode = document.getElementById('info');
infoNode.addEventListener('click', () => {
if (infoNode.style.top) {
// clear inline top style
infoNode.style.top = '';
} else {
// set top to client height + 2 * border thickness
infoNode.style.top = `calc(100% - ${infoNode.clientHeight}px - 4px)`;
}
});
#info {
font-size: 16px;
width: 200px;
border: 2px solid hsl(0, 0%, 80%);
padding: 8px;
border-radius: 4px;
cursor: pointer;
position: fixed;
/* 100% height of the viewport subtracting:
tab height: padding, margin, & font size */
top: calc(100% - (8px + 8px + 24px));
/* we center the tab horizontally here using
50% the width of the viewport - 50% the fixed
width of the tab */
left: calc(50% - 200px/2);
transition: top 0.5s;
}
.title {
font-size: 24px;
font-weight: 500;
margin-bottom: 8px;
display: block;
}
p {
margin: 0;
}
<div id="info">
<span class="title">Click on Me</span>
<p>
This is the content of the tab, isn't it great? I think so too, and it can be of any arbitrary length!
</p>
</div>
Basically the trick is to use calc with top instead of -100% with bottom for your positioning, then your tab is initially rendered in the correct position and you don't have to worry it being out of place when a visitor first loads your page.

how to disable dragend animation in html5

I created a draggable element by setting its draggable attribute. When I drop the element, there is an animation of the element snapping back to its origin position:
How can the snap-back animation be disabled? I tried calling preventDefault() on the dragend event, but it had no effect on the animation.
The following snippet shows the basics:
document.getElementById('test').addEventListener(
'dragend', evt => {
evt.preventDefault();
}
);
#container {
border: 1px solid black;
min-width: 300px;
min-height: 200px;
position: relative;
}
#test {
width: 50px;
height: 50px;
background-color: red;
position: absolute;
top: 25px;
left: 40px;
}
<div id="container">
<div id="test" draggable='true'></div>
</div>
Not every browser will show the dragged #test jumping back to the original position.
In order to prevent the animation, you need the drop event to fire. For the drop event to fire, you need to call preventDefault() in the handler for dragover.
document.addEventListener('dragover', function(e) { e.preventDefault() })
Example in MDN docs shows the same thing: https://developer.mozilla.org/en-US/docs/Web/Events/drop#Example
An old blog post describing the quirks of HTML5 Drag and Drop API: https://www.quirksmode.org/blog/archives/2009/09/the_html5_drag.html
As was said earlier, you need to explicitly describe onDragOver handler on the parent's container (where you will drop your draggable element) and put .preventDefault() on event to prevent this animation.
Here is a simple React code example for better understanding of this mechanic (you can position the box inside the container by dragging it):
App.jsx
import './App.css'
const App = () => {
function handleDragOver(e) {
e.preventDefault()
}
function handleDrop(e) {
let box = document.getElementById('box')
if (box) {
box.style.top = e.clientY + 'px'
box.style.left = e.clientX + 'px'
}
}
return (
<div className="container" onDragOver={handleDragOver} onDrop={handleDrop}>
<div id="box" draggable></div>
</div>
)
}
export default App
App.css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 100vw;
height: 100vh;
position: relative;
}
#box {
width: 100px;
height: 100px;
background-color: lightgreen;
position: absolute;
}

How to align Navbar at bottom of window, but have content under this in CSS?

I need help with this website I'm making for a project at school. I need help with the Nav bar at the bottom of the window when you first load the page but if you scroll down it scrolls with the page. I need it to basically align to the bottom of the window when its first loaded. I can't for the life of me figure out how to do it. Here is a reference.
Example Website
Notice how the Nav bar is always at the bottom of the window when scrolled to the top even if you resize the window. I would like to do this with only CSS and HTML, but I understand a little bit of Javascript so if It can't be done with only CSS and HTML it's alright. Thanks for the help.
The magic is in using both JQuery and CSS.
JQuery
$(document).ready(function () {
var navBarY = $(".bottom-bar").offset().top;
$(document).scroll(function () {
if ($(window).scrollTop() >= navBarY) {
$(".bottom-bar").addClass("fixed-top");
} else {
$(".bottom-bar").removeClass("fixed-top");
}
});
});
Whenever the .bottom-bar reaches the top of the window a class fixed-top is added.
CSS
.fixed-top {
position: fixed;
margin-top: 0 !important;
}
Example
$(document).ready(function () {
var navBarY = $(".bottom-bar").offset().top;
$(document).scroll(function () {
if ($(window).scrollTop() >= navBarY) {
$(".bottom-bar").addClass("fixed-top");
} else {
$(".bottom-bar").removeClass("fixed-top");
}
});
});
body {
margin: 0px;
font-family: Helvetica, Arial;
height: 2000px;
}
.bottom-bar {
width: 100%;
height: 40px;
background: #2A2A2A;
color: white;
text-align: center;
line-height: 40px;
margin-top: calc(100vh - 40px);
}
.fixed-top {
position: fixed;
margin-top: 0 !important;
}
<nav class="bottom-bar">Navigation bar</nav>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>

Get away with built-in dragging html elements

I have a problem with html-objects that moving when I´m dragging them, you know the transparent "ghost" -copy of the element that appears when you holding down the mouse and drag it. My problem is that it interrupt my mouse event. I have a image that should be able to move inside a div when you dragging it with the mouse. I have to events for that, first one for mousedown that trigger mousemove-event, mousemove handles the movement of the image. mousedown is no problem but when I´m moving the mouse with the button down the transparent "ghost" - copy of the elements appear and interrupt my mousemove-event. Is that any one how knows how to get around or fix this thing?
Could you provide a sample?
From what it sounds like, the first thing to check is that the events are actually being hit. Writing messages out to console whenever each event fires should help prove or disprove that the events are occurring as-expected.
Then you start your mousemove event, set a timeout for the appended class 'hide' in 0 ms. Its work.
const dragAndDrop = () => {
const card = document.querySelector('.dragDrop');
const cells = document.querySelectorAll('.block');
const dragStart = function () {
// i added timeout for appended class
setTimeout(() => {
this.classList.add('hide');
}, 0);
};
const dragEnd = function () {
// i added timeout for appended class
setTimeout(() => {
this.classList.remove('hide');
}, 0);
};
const dragOver = function (event) {
event.preventDefault();
}
const dragEnter = function (event) {
event.preventDefault()
this.classList.add('hovered');
}
const dragLeave = function () {
this.classList.remove('hovered');
}
const dragDrop = function () {
this.append(card);
this.classList.remove('hovered')
}
cells.forEach((cell) => {
cell.addEventListener('dragover', dragOver);
cell.addEventListener('dragenter', dragEnter);
cell.addEventListener('dragleave', dragLeave);
cell.addEventListener('drop', dragDrop);
})
card.addEventListener('dragstart', dragStart);
card.addEventListener('dragend', dragEnd);
}
dragAndDrop()
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
width: 100%;
height: 100vh;
display: flex;
justify-content: space-around;
padding-top: 20px;
}
.block{
width: 100px;
height: 100px;
background-color: rgb(99, 99, 99);
display: flex;
justify-content: center;
align-items: center;
}
.card{
width: 80px;
height: 60px;
background-color: black;
cursor: grab;
}
.hide {
display: none;
}
.hovered {
background-color: rgb(254, 164, 164);
}
<div class="block">
<div draggable="true" class="drag dragDrop">
<div class="card"></div>
<div class="text">Hello, world</div>
</div>
</div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
I wrote this 12 years ago but if I remember right the solution was something like,
imageElement.addEventListener('dragover', function(e) {
e.preventDefault()
});
This should prevent the user from clicking and dragging on the image which means the browser won't add any visual effects.