CSS链接动画导致未点击链接提前显示visited颜色及动画状态异常问题求助
CSS链接动画导致未点击链接提前显示visited颜色及动画状态异常问题求助
我刚接触CSS,最近一直在尝试关键帧动画,目前同时用CSS和JS实现以下效果:
- 鼠标悬停链接时应用第一个关键帧动画
- 鼠标离开链接但未点击时应用第二个动画
- 点击链接时应用第三个动画(同时用JS延迟导航,让动画能播放完,但只在第一次点击时生效,之后恢复正常链接行为)
现在遇到的核心问题是:所有链接在未点击前就显示了:visited的颜色。我确定这和关键帧动画的设置有关,但找不到原因——鼠标悬停进入的动画以未访问链接颜色开始,悬停离开的动画以currentColor结束。如果把currentColor改成未访问链接的颜色,链接又会完全忽略:visited的颜色。
我觉得点击动画应该不是问题所在,因为它只在:active触发后才生效(我也试过:focus但没区别),不过它确实会在结束时停在已访问链接颜色。
(还有其他小问题,比如页面加载时悬停离开动画会播放(尽管设置了暂停),浏览器在页面刷新后不记住已访问状态,但如果链接颜色能正常工作,这些我可以接受。)
或者会不会是JS的问题?我对JS完全不熟悉,这段JS是别人帮我写的。
补充:我给关键帧动画加了animation-fill-mode: none;,但没效果。
补充2:修复了CSS里的链接颜色,但悬停离开动画的结束状态还是默认变成黑色
补充3:修复了默认颜色,但似乎没有纯CSS方案能让悬停离开动画从黑色淡入到当前链接颜色——它总是默认变成黑色或偏红的颜色,而不是根据链接当前的:link(偏红)或:visited(黑色)状态来变化。
用到的JS代码
document.querySelectorAll('a:not(.sitenav a):not(.footer a)').forEach(function (link) { let isAnimating = false; // Flag to track if animation is already happening const linkId = link.href; // Use the link's href as a unique identifier let hasAnimatedOnce = localStorage.getItem(linkId) === 'true'; // Retrieve the value from localStorage link.addEventListener('click', function (e) { // If the link has been clicked before (stored in localStorage), allow normal behavior if (hasAnimatedOnce) { return; // Normal navigation will happen } // If animation is already happening, ignore the click if (isAnimating) { return; // Do nothing if animation is in progress } // Prevent default navigation behavior to wait for the animation e.preventDefault(); // Mark that the animation is starting isAnimating = true; // Reset the animation by removing it first (so it can be reapplied) this.style.animation = ''; // Remove the animation to allow it to play again // Trigger the animation by adding the animation property again this.style.animation = 'active-animation 3s forwards'; // Adjust timing as necessary // Store the linkElement to use later in the animationend handler this._linkElement = this; }); // Separate animationend listener outside of click event listener link.addEventListener('animationend', function () { // If the link element was stored and animation is complete if (this._linkElement) { // Now navigate to the link's href after the animation finishes window.location.href = this._linkElement.href; // Reset the animation flag so the link can be clicked again isAnimating = false; // Mark that the link has been clicked and animated once hasAnimatedOnce = true; // Save the state to localStorage so the flag persists across sessions localStorage.setItem(linkId, 'true'); // Clear the stored link element reference delete this._linkElement; } }); });
用到的CSS代码
/* Base state for the link - initial color is reddish */ a:link { position: relative; /* Ensure the link is positioned */ z-index: 1; /* Ensure the link is above other elements */ color: #660e0e; /* Start as reddish */ pointer-events: auto; text-decoration: none; transition: color 0.4s ease; } a:not(.sitenav a):not(.footer a) { animation-play-state: paused; /* Prevent any animation from starting initially */ pointer-events: auto; position: relative; /* Ensure the link is positioned */ text-decoration: none; } /* Ensuring the link remains clickable during the animation */ a:hover { pointer-events: auto; /* Ensures pointer events remain enabled */ } /* Hover-in animation for normal hover effect (only when not clicked) */ a:not(.sitenav a):not(.footer a):not(:active):hover { animation: hover-in 3s forwards; /* Add hover animation */ } /* Hover-out animation when the mouse leaves, but only if the link hasn't been clicked */ a:not(.sitenav a):not(.footer a):not(:active):not(:hover) { animation: hover-out 4s none cubic-bezier(.45,.05,.55,.95); } /* visited link */ a:visited { color: black; } /* selected link */ a:not(.sitenav a):not(.footer a):active { animation-name: active-animation; animation-duration: 3s; animation-fill-mode: none; } /* Active link animation (bright red -> black) */ @keyframes active-animation { 0% { color: #b80909; /* Start as bright red */ text-shadow: 0 0 20px darkred, text-shadow: 0 0 5px brown; } 10% { font-size: 1.02em; /* embiggen */ color: #b80909; text-shadow: 0 0 20px darkred, text-shadow: 0 0 10px brown; } 20% { color: black; /* Fade back to black */ } 30% { font-size: 1.04em; } 60% { text-shadow: 0 0 10px darkred, 0 0 5px brown; font-size: ''; /* shrink again */ } 100% { text-shadow: 0 0 0px darkred, text-shadow: 0 0 0px brown; color: ''; } } /* Hover-in animation (reddish to black with shadow) */ @keyframes hover-in { 0% { color: ''; /* Start as link or visited */ text-shadow: none; } 100% { color: black; text-shadow: 0 0 30px #850000, 0 0 10px #110402, 0 0 5px #110402; } } /* Hover-out animation (black to prev color with shadow fading) */ @keyframes hover-out { 0% { color: black; text-shadow: 0 0 30px #850000, 0 0 10px #110402, 0 0 5px #110402; } 50% { color: black; text-shadow: 0 0 20px #850000, 0 0 5px #110402, 0 0 3px #110402; } 100% { color: ''; /* return to prev state? */ } }
用到的HTML代码
<!doctype html> <html> <head> <script type="text/javascript" src="CC-xxxCSS/CC-scripts.js" defer></script> <script type="text/javascript" src="CC-xxxCSS/fragment-loader.js" defer></script> <script type="text/javascript" src="CC-xxxCSS/base-navigation.js" defer></script> <link rel="stylesheet" type="text/css" href="CC-xxxCSS/CC-styles.css"> <script src="https://code.jquery.com/jquery-3.7.1.slim.js" integrity="sha256-UgvvN8vBkgO0luPSUl2s8TIlOSYRoGFAX4jlCIm9Adc=" crossorigin="anonymous"></script> </head> <body> <div> <p>Fonts used on this website:</p> <ul> <li><a href="https://www.1001freefonts.com/black-castle-mf.font">Black Castle MF</a></li> <li><a href="http://www.dafont.com/blackletter-hplhs.font">Blackletter HPLHS</a></li> <li><a href="https://www.dafont.com/chomsky.font">Chomsky</a></li> <li><a href="https://freefontsfamily.org/trajan-pro-font-free/">Trajan Pro</a></li> <li><a href="http://www.dafont.com/ww2blackletter.font">WW2 Blackletter HPLHS</a></li> </ul> </div> </body> </html>
备注:内容来源于stack exchange,提问作者K-RAM
相关产品推荐
相关产品推荐

