admin管理员组

文章数量:1293520

I have a button where I'd like a slightly transparent overlay to 'glide through' the button on hover.

There is something called the 'ripple effect' that you usually can achieve by clicking on a button.

Like here:

HTML:

<div class="container">
    <a data-animation="ripple">Click Me</a>
</div>

CSS:

:root {
    /* if u want to change the color of
     * the ripple change this value
    */
    --color-ripple: rgba(255,255,255,0.8);
}

body {
    background: #36353c;
}

.container {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    height: 50px;
    width: 200px;
    margin: auto;
}
*[data-animation="ripple"] {
    position: relative; /*Position relative is required*/
    height: 100%;
    width: 100%;
    display: block;
    outline: none;:root {
    /* if u want to change the color of
     * the ripple change this value
    */
    --color-ripple: rgba(255, 255, 255, 0.8);
}

body {
    background: #36353c;
}

.container {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    height: 50px;
    width: 200px;
    margin: auto;
}
*[data-animation="ripple"] {
    position: relative; /*Position relative is required*/
    height: 100%;
    width: 100%;
    display: block;
    outline: none;
    padding: 20px;
    color: #fff;
    text-transform: uppercase;
    background: linear-gradient(135deg, #e570e7 0%, #79f1fc 100%);
    box-sizing: border-box;
    text-align: center;
    line-height: 14px;
    font-family: roboto, helvetica;
    font-weight: 200;
    letter-spacing: 1px;
    text-decoration: none;
    box-shadow: 0 5px 3px rgba(0, 0, 0, 0.3);
    cursor: pointer;
    /*border-radius: 50px;*/
    -webkit-tap-highlight-color: transparent;
}

*[data-animation="ripple"]:focus {
    outline: none;
}

*[data-animation="ripple"]::selection {
    background: transparent;
    pointer-events: none;
}

    padding: 20px;
    color: #fff;
    text-transform: uppercase;
    background: linear-gradient(135deg, #e570e7 0%,#79f1fc 100%);
    box-sizing: border-box;
    text-align: center;
    line-height: 14px;
    font-family: roboto, helvetica;
    font-weight: 200;
    letter-spacing: 1px;
    text-decoration: none;
    box-shadow: 0 5px 3px rgba(0, 0, 0, 0.3);
    cursor: pointer;
  /*border-radius: 50px;*/
    -webkit-tap-highlight-color: transparent;
}

*[data-animation="ripple"]:focus {
    outline: none;
}

*[data-animation="ripple"]::selection {
    background: transparent;
    pointer-events: none;
}

JS:

const isMobile = window.navigator.userAgent.match(/Mobile/) && window.navigator.userAgent.match(/Mobile/)[0] === "Mobile";
const event = isMobile ? "touchstart" : "click";

const button = document.querySelectorAll('*[data-animation="ripple"]'),
            container = document.querySelector(".container");

for (var i = 0; i < button.length; i++) {
    const currentBtn = button[i];

    currentBtn.addEventListener(event, function(e) {

        e.preventDefault();
        const button = e.target,
                    rect = button.getBoundingClientRect(),
                    originalBtn = this,
                    btnHeight = rect.height,
                    btnWidth = rect.width;
        let posMouseX = 0,
                posMouseY = 0;

        if (isMobile) {
            posMouseX = e.changedTouches[0].pageX - rect.left;
            posMouseY = e.changedTouches[0].pageY - rect.top;
        } else {
            posMouseX = e.x - rect.left;
            posMouseY = e.y - rect.top;
        }

        const baseCSS =  `position: absolute;
                                            width: ${btnWidth * 2}px;
                                            height: ${btnWidth * 2}px;
                                            transition: all linear 700ms;
                                            transition-timing-function:cubic-bezier(0.250, 0.460, 0.450, 0.940);
                                            border-radius: 50%;
                                            background: var(--color-ripple);
                                            top:${posMouseY - btnWidth}px;
                                            left:${posMouseX - btnWidth}px;
                                            pointer-events: none;
                                            transform:scale(0)`

        var rippleEffect = document.createElement("span");
        rippleEffect.style.cssText = baseCSS;

        //prepare the dom
        currentBtn.style.overflow = "hidden";
        this.appendChild(rippleEffect);

        //start animation
        setTimeout( function() { 
            rippleEffect.style.cssText = baseCSS + `transform:scale(1); opacity: 0;`;
        }, 5);

        setTimeout( function() {
            rippleEffect.remove();
            //window.location.href = currentBtn.href;
        },700);
    })
}

Is it possible to achieve something similar without having to click on the button but just hovering over it?

I have a button where I'd like a slightly transparent overlay to 'glide through' the button on hover.

There is something called the 'ripple effect' that you usually can achieve by clicking on a button.

Like here: https://codepen.io/tomma5o/pen/zwyKya

HTML:

<div class="container">
    <a data-animation="ripple">Click Me</a>
</div>

CSS:

:root {
    /* if u want to change the color of
     * the ripple change this value
    */
    --color-ripple: rgba(255,255,255,0.8);
}

body {
    background: #36353c;
}

.container {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    height: 50px;
    width: 200px;
    margin: auto;
}
*[data-animation="ripple"] {
    position: relative; /*Position relative is required*/
    height: 100%;
    width: 100%;
    display: block;
    outline: none;:root {
    /* if u want to change the color of
     * the ripple change this value
    */
    --color-ripple: rgba(255, 255, 255, 0.8);
}

body {
    background: #36353c;
}

.container {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    height: 50px;
    width: 200px;
    margin: auto;
}
*[data-animation="ripple"] {
    position: relative; /*Position relative is required*/
    height: 100%;
    width: 100%;
    display: block;
    outline: none;
    padding: 20px;
    color: #fff;
    text-transform: uppercase;
    background: linear-gradient(135deg, #e570e7 0%, #79f1fc 100%);
    box-sizing: border-box;
    text-align: center;
    line-height: 14px;
    font-family: roboto, helvetica;
    font-weight: 200;
    letter-spacing: 1px;
    text-decoration: none;
    box-shadow: 0 5px 3px rgba(0, 0, 0, 0.3);
    cursor: pointer;
    /*border-radius: 50px;*/
    -webkit-tap-highlight-color: transparent;
}

*[data-animation="ripple"]:focus {
    outline: none;
}

*[data-animation="ripple"]::selection {
    background: transparent;
    pointer-events: none;
}

    padding: 20px;
    color: #fff;
    text-transform: uppercase;
    background: linear-gradient(135deg, #e570e7 0%,#79f1fc 100%);
    box-sizing: border-box;
    text-align: center;
    line-height: 14px;
    font-family: roboto, helvetica;
    font-weight: 200;
    letter-spacing: 1px;
    text-decoration: none;
    box-shadow: 0 5px 3px rgba(0, 0, 0, 0.3);
    cursor: pointer;
  /*border-radius: 50px;*/
    -webkit-tap-highlight-color: transparent;
}

*[data-animation="ripple"]:focus {
    outline: none;
}

*[data-animation="ripple"]::selection {
    background: transparent;
    pointer-events: none;
}

JS:

const isMobile = window.navigator.userAgent.match(/Mobile/) && window.navigator.userAgent.match(/Mobile/)[0] === "Mobile";
const event = isMobile ? "touchstart" : "click";

const button = document.querySelectorAll('*[data-animation="ripple"]'),
            container = document.querySelector(".container");

for (var i = 0; i < button.length; i++) {
    const currentBtn = button[i];

    currentBtn.addEventListener(event, function(e) {

        e.preventDefault();
        const button = e.target,
                    rect = button.getBoundingClientRect(),
                    originalBtn = this,
                    btnHeight = rect.height,
                    btnWidth = rect.width;
        let posMouseX = 0,
                posMouseY = 0;

        if (isMobile) {
            posMouseX = e.changedTouches[0].pageX - rect.left;
            posMouseY = e.changedTouches[0].pageY - rect.top;
        } else {
            posMouseX = e.x - rect.left;
            posMouseY = e.y - rect.top;
        }

        const baseCSS =  `position: absolute;
                                            width: ${btnWidth * 2}px;
                                            height: ${btnWidth * 2}px;
                                            transition: all linear 700ms;
                                            transition-timing-function:cubic-bezier(0.250, 0.460, 0.450, 0.940);
                                            border-radius: 50%;
                                            background: var(--color-ripple);
                                            top:${posMouseY - btnWidth}px;
                                            left:${posMouseX - btnWidth}px;
                                            pointer-events: none;
                                            transform:scale(0)`

        var rippleEffect = document.createElement("span");
        rippleEffect.style.cssText = baseCSS;

        //prepare the dom
        currentBtn.style.overflow = "hidden";
        this.appendChild(rippleEffect);

        //start animation
        setTimeout( function() { 
            rippleEffect.style.cssText = baseCSS + `transform:scale(1); opacity: 0;`;
        }, 5);

        setTimeout( function() {
            rippleEffect.remove();
            //window.location.href = currentBtn.href;
        },700);
    })
}

Is it possible to achieve something similar without having to click on the button but just hovering over it?

Share Improve this question asked Jan 14, 2018 at 19:54 Radical_ActivityRadical_Activity 2,73811 gold badges45 silver badges80 bronze badges 2
  • hmm do you want the ripple origin to be wherever the mouse enters? or a fixed, centred origin? – Facundo Corradini Commented Jan 14, 2018 at 20:14
  • I edited the answer for an effect closer to the original. Please check if that works for you ;) – Facundo Corradini Commented Jan 15, 2018 at 10:55
Add a ment  | 

2 Answers 2

Reset to default 5

Replace line 2 of JS:

const event = isMobile ? "touchstart" : "click";

with:

const event = isMobile ? "touchstart" : "mouseover";

That would do the job.

Hope that helps!

If you want the ripple origin to be fixed (e.g. from the middle) instead of from wherever the mouse enters, the answer is much simpler and requires no javascript: just stack a semi-transparent rounded pseudo-element and animate the scale on hover.

body {
	background: #36353c;
}

.container {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	height: 50px;
	width: 200px;
	margin: auto;
}
.ripple{
	position: relative; /*Position relative is required*/
	height: 100%;
	width: 100%;
	display: block;
	outline: none;
	padding: 20px;
	color: #fff;
	text-transform: uppercase;
	background: linear-gradient(135deg, #e570e7 0%,#79f1fc 100%);
	box-sizing: border-box;
	text-align: center;
	line-height: 14px;
	font-family: roboto, helvetica;
	font-weight: 200;
	letter-spacing: 1px;
	text-decoration: none;
	box-shadow: 0 5px 3px rgba(0, 0, 0, 0.3);
	cursor: pointer;
	overflow:hidden;
}

.ripple:hover:before{
	animation: ripple 1s ease;
}

.ripple:before{
	content:"";
	position:absolute; top:0; left:0;
	width:100%; height:100%;
  background-color:rgba(255, 255, 255, 0.7);
  border-radius:50%;
	transform:scale(0);
}

@keyframes ripple{
	from{transform:scale(0); opacity:1;}
	to{transform:scale(3);opacity:0;}
}
<div class="container">
	<a class="ripple">Hover Me</a>
</div>

本文标签: javascriptCSS ripple effect on HoverStack Overflow