Files
portfolio/app/assets/css/transitions.css
2025-11-10 18:09:18 +03:30

196 lines
3.6 KiB
CSS

/**
* Page & Layout Transitions
* Nuxt 4 transition styles for smooth page navigation
*/
/* CSS Custom Properties for Transitions */
:root {
--transition-duration-fast: 150ms;
--transition-duration-base: 250ms;
--transition-duration-slow: 350ms;
--transition-timing: cubic-bezier(0.4, 0, 0.2, 1);
--transition-timing-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
/* Page Transitions */
.page-enter-active,
.page-leave-active {
transition: all var(--transition-duration-base) var(--transition-timing);
}
.page-enter-from {
opacity: 0;
transform: translateY(10px);
}
.page-leave-to {
opacity: 0;
transform: translateY(-10px);
}
/* Layout Transitions */
.layout-enter-active,
.layout-leave-active {
transition: all var(--transition-duration-base) var(--transition-timing);
}
.layout-enter-from {
opacity: 0;
filter: blur(4px);
}
.layout-leave-to {
opacity: 0;
filter: blur(4px);
}
/* Staggered List Animations - Client-side only to avoid hydration mismatch */
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Fade In Animation */
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.fade-in {
animation: fadeIn var(--transition-duration-base) var(--transition-timing);
}
/* Scale Fade Animation (for modals, dropdowns) */
@keyframes scaleFadeIn {
from {
opacity: 0;
transform: scale(0.95);
}
to {
opacity: 1;
transform: scale(1);
}
}
.scale-fade-in {
animation: scaleFadeIn var(--transition-duration-fast) var(--transition-timing);
}
/* Slide In Animations */
@keyframes slideInFromRight {
from {
opacity: 0;
transform: translateX(20px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes slideInFromLeft {
from {
opacity: 0;
transform: translateX(-20px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
.slide-in-right {
animation: slideInFromRight var(--transition-duration-base) var(--transition-timing);
}
.slide-in-left {
animation: slideInFromLeft var(--transition-duration-base) var(--transition-timing);
}
/* View Transitions API Custom Animations */
@supports (view-transition-name: main) {
/* Main content area */
.view-transition-main {
view-transition-name: main;
}
/* Slide transition for navigation */
::view-transition-old(main) {
animation: slideOutLeft 250ms cubic-bezier(0.4, 0, 0.2, 1);
}
::view-transition-new(main) {
animation: slideInRight 250ms cubic-bezier(0.4, 0, 0.2, 1);
}
@keyframes slideOutLeft {
from {
transform: translateX(0);
opacity: 1;
}
to {
transform: translateX(-20px);
opacity: 0;
}
}
@keyframes slideInRight {
from {
transform: translateX(20px);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
/* Crossfade for content areas */
::view-transition-old(root),
::view-transition-new(root) {
animation-duration: 300ms;
}
}
/* Reduced Motion Support */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
.page-enter-active,
.page-leave-active,
.layout-enter-active,
.layout-leave-active {
transition: none !important;
}
.page-enter-from,
.page-leave-to,
.layout-enter-from,
.layout-leave-to {
transform: none !important;
filter: none !important;
}
/* Disable View Transitions for reduced motion */
::view-transition-old(*),
::view-transition-new(*) {
animation: none !important;
}
}