Popup弹窗外部单次点击无法关闭及添加隐藏反向动画问题求助
Hey there! Let's work through those two popup issues you're facing—they're pretty common, and we can fix them with a few targeted tweaks to your code.
Problem 1: Single Click Outside Doesn't Close the Popup
What's going wrong?
Right now, your code only hides the popup when there's no text selected in the textarea on mouseup. There's no logic to detect clicks outside the popup itself to trigger a close. Also, if you click the popup directly, we don't want it to close—we need to ignore those clicks to prevent accidental closures.
The Fix
We'll add a click event listener to the entire document. When a click happens, we'll check if the target is the popup or inside it. If not, we'll trigger the popup to hide. We'll also stop event propagation when clicking the popup so the document-level click doesn't fire.
Problem 2: Reverse Transition Animation When Hiding the Popup
What's going wrong?
Using display:none immediately removes the element from the DOM, which means any transition or animation won't run—there's nothing left to animate! Instead, we need to use properties that let the element stay in the DOM while animating out, like opacity and visibility.
The Fix
We'll adjust the CSS to use opacity: 0 and visibility: hidden for the hidden state instead of display:none. We'll also create a reverse rotation animation and use class toggles to manage the show/hide states, making it easy to trigger the correct animations.
Updated Complete Code
JavaScript
function getSelected() { if(window.getSelection) { return window.getSelection(); } else if(document.getSelection) { return document.getSelection(); } else { var selection = document.selection && document.selection.createRange(); if(selection.text) { return selection.text; } return false; } return false; } $(document).ready(function() { const $popup = $("span.popup-tag"); $('#my-textarea').mouseup(function(event) { var selection = getSelected(); selection = $.trim(selection); if(selection != ''){ // Show popup with rotation animation $popup.text(selection) .css({ top: event.clientY, left: event.clientX }) .removeClass('popup-tag--hidden') .addClass('popup-tag--visible'); } else { // Hide popup with reverse animation hidePopup(); } }); // Close popup when clicking outside of it $(document).click(function(event) { if (!$popup.is(event.target) && $popup.has(event.target).length === 0) { hidePopup(); } }); // Prevent clicks on the popup from triggering the close action $popup.click(function(event) { event.stopPropagation(); }); // Helper function to handle smooth popup closure function hidePopup() { $popup.removeClass('popup-tag--visible').addClass('popup-tag--hidden'); // Optional: After animation finishes, set display:none to free up layout space setTimeout(() => { if ($popup.hasClass('popup-tag--hidden')) { $popup.css('display', 'none'); } }, 600); // Match the duration of your animation } });
CSS
.popup-tag { position: absolute; display: none; /* Start fully hidden */ opacity: 0; visibility: hidden; background-color: #785448d4; color: white; padding: 10px; font-size: 20px; font-weight: bold; text-decoration: underline; cursor: pointer; box-shadow: 0px 0px 1px 5000px rgba(0,0,0,0.8); -webkit-filter: drop-shadow(0 1px 10px rgba(113,158,206,0.8)); transition: opacity 0.6s ease-in-out, visibility 0.6s ease-in-out; } /* Show state with forward rotation animation */ .popup-tag--visible { display: block; opacity: 1; visibility: visible; -webkit-animation: rotate-center .6s ease-in-out both; animation: rotate-center .6s ease-in-out both; } /* Hide state with reverse rotation and fade-out */ .popup-tag--hidden { opacity: 0; visibility: hidden; -webkit-animation: rotate-center-reverse .6s ease-in-out both; animation: rotate-center-reverse .6s ease-in-out both; } @-webkit-keyframes rotate-center { 0% {-webkit-transform: rotate(0); transform: rotate(0)} 100% {-webkit-transform: rotate(360deg); transform: rotate(360deg)} } @keyframes rotate-center { 0% {-webkit-transform: rotate(0); transform: rotate(0)} 100% {-webkit-transform: rotate(360deg); transform: rotate(360deg)} } @-webkit-keyframes rotate-center-reverse { 0% {-webkit-transform: rotate(360deg); transform: rotate(360deg)} 100% {-webkit-transform: rotate(0); transform: rotate(0)} } @keyframes rotate-center-reverse { 0% {-webkit-transform: rotate(360deg); transform: rotate(360deg)} 100% {-webkit-transform: rotate(0); transform: rotate(0)} }
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script> Select any text :<br> <div type="text" id="my-textarea" style="width:100%; height:200px;" > While delivering a lecture at the Indian Institute of Management Shillong, Kalam collapsed and died from an apparent cardiac arrest on 27 July 2015, aged 83. Thousands including national-level dignitaries attended the funeral ceremony held in his hometown of Rameshwaram, where he was buried with full state honours. </div> <span class="popup-tag"></span>
Key Changes Breakdown
- Click Outside Closure: We added a document click listener that checks if the click isn't targeting the popup, then triggers the hide function. We also stop event propagation on popup clicks to keep it open when users interact with it.
- Reverse Animation: We created a reverse rotation animation and used CSS classes to toggle visibility/opacity instead of
display:nonedirectly. The setTimeout ensures we only setdisplay:noneafter the animation completes, so the transition is fully visible.
内容的提问来源于stack exchange,提问作者Rakesh Suthar

