✨ CSS Transitions

Smooth Property Changes

CSS Transitions

Create smooth animations between property values. Transitions add polish and improve user experience by making changes feel natural.

💻 Transition Basics

/* Basic transition */
.button {
    background: #007bff;
    transition: background 0.3s;
}

.button:hover {
    background: #0056b3;
}

/* Four transition properties */
.element {
    transition-property: background;
    transition-duration: 0.3s;
    transition-timing-function: ease;
    transition-delay: 0s;
}

/* Shorthand */
.element {
    transition: property duration timing-function delay;
    transition: background 0.3s ease 0s;
}

🎯 Transition Properties

transition-property

/* Single property */
.box {
    transition-property: background;
}

/* Multiple properties */
.box {
    transition-property: background, color, transform;
}

/* All properties */
.box {
    transition-property: all;
}

/* None (no transition) */
.box {
    transition-property: none;
}

/* Specific properties recommended */
.button {
    transition-property: background-color, transform;
}

transition-duration

/* Duration in seconds */
.fast {
    transition-duration: 0.2s;
}

.medium {
    transition-duration: 0.5s;
}

.slow {
    transition-duration: 1s;
}

/* Duration in milliseconds */
.precise {
    transition-duration: 150ms;
}

/* Multiple durations for multiple properties */
.box {
    transition-property: background, transform;
    transition-duration: 0.3s, 0.5s;
}

/* Common durations */
/* Micro: 100ms - 150ms */
/* Quick: 200ms - 300ms */
/* Standard: 300ms - 500ms */
/* Slow: 500ms - 1s */

transition-timing-function

/* Predefined timing functions */
.ease {
    transition-timing-function: ease;  /* Default, slow-fast-slow */
}

.linear {
    transition-timing-function: linear;  /* Constant speed */
}

.ease-in {
    transition-timing-function: ease-in;  /* Slow start */
}

.ease-out {
    transition-timing-function: ease-out;  /* Slow end */
}

.ease-in-out {
    transition-timing-function: ease-in-out;  /* Slow start and end */
}

/* Cubic bezier (custom) */
.custom {
    transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}

/* Steps (discrete transitions) */
.steps {
    transition-timing-function: steps(4);  /* 4 equal steps */
    transition-timing-function: steps(4, jump-start);
    transition-timing-function: steps(4, jump-end);
}

/* Common custom beziers */
.smooth {
    transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);  /* Material Design */
}

.bounce {
    transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55);
}

transition-delay

/* Delay before transition starts */
.delayed {
    transition-delay: 0.5s;
}

.immediate {
    transition-delay: 0s;  /* Default */
}

/* Multiple delays */
.box {
    transition-property: opacity, transform;
    transition-duration: 0.3s, 0.5s;
    transition-delay: 0s, 0.2s;  /* Transform delayed */
}

/* Negative delay (start partway through) */
.advanced {
    transition-delay: -0.2s;  /* Starts 0.2s in */
}

✍️ Transition Shorthand

/* Full shorthand syntax */
.element {
    transition: property duration timing-function delay;
}

/* Examples */
.button {
    transition: background 0.3s ease 0s;
}

.card {
    transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Multiple transitions */
.box {
    transition: 
        background 0.3s ease,
        transform 0.5s ease-out,
        opacity 0.2s linear;
}

/* All properties, same settings */
.element {
    transition: all 0.3s ease;
}

/* Common pattern */
.interactive {
    transition: all 0.3s;  /* Shorthand shorthand */
}

🎨 Common Transitions

Opacity

/* Fade in/out */
.fade {
    opacity: 0;
    transition: opacity 0.3s;
}

.fade.visible {
    opacity: 1;
}

/* Hover fade */
.image {
    opacity: 1;
    transition: opacity 0.3s;
}

.image:hover {
    opacity: 0.7;
}

Transform

/* Scale */
.scale {
    transition: transform 0.3s;
}

.scale:hover {
    transform: scale(1.1);
}

/* Translate (move) */
.slide {
    transition: transform 0.3s;
}

.slide:hover {
    transform: translateY(-5px);
}

/* Rotate */
.rotate {
    transition: transform 0.3s;
}

.rotate:hover {
    transform: rotate(45deg);
}

/* Combine transforms */
.combo {
    transition: transform 0.3s;
}

.combo:hover {
    transform: scale(1.05) translateY(-5px);
}

Colors

/* Background color */
.button {
    background: #007bff;
    transition: background-color 0.3s;
}

.button:hover {
    background: #0056b3;
}

/* Text color */
.link {
    color: #007bff;
    transition: color 0.2s;
}

.link:hover {
    color: #0056b3;
}

/* Border color */
.input {
    border: 2px solid #ccc;
    transition: border-color 0.3s;
}

.input:focus {
    border-color: #007bff;
}

Dimensions

/* Width */
.expand {
    width: 200px;
    transition: width 0.3s;
}

.expand:hover {
    width: 300px;
}

/* Height */
.accordion {
    height: 0;
    overflow: hidden;
    transition: height 0.3s;
}

.accordion.open {
    height: 200px;
}

/* Max-height trick for dynamic content */
.collapsible {
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.3s ease-out;
}

.collapsible.open {
    max-height: 1000px;  /* Large enough for content */
}

Box Shadow

/* Elevate on hover */
.card {
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    transition: box-shadow 0.3s;
}

.card:hover {
    box-shadow: 0 10px 20px rgba(0,0,0,0.2);
}

🎯 Practical Examples

/* Button hover effect */
.button {
    background: #007bff;
    color: white;
    padding: 10px 20px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    transition: background-color 0.3s, transform 0.2s;
}

.button:hover {
    background: #0056b3;
    transform: translateY(-2px);
}

.button:active {
    transform: translateY(0);
}

/* Card hover effect */
.card {
    background: white;
    border-radius: 8px;
    padding: 20px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    transition: transform 0.3s, box-shadow 0.3s;
}

.card:hover {
    transform: translateY(-5px);
    box-shadow: 0 10px 20px rgba(0,0,0,0.15);
}

/* Link underline animation */
.link {
    position: relative;
    color: #007bff;
    text-decoration: none;
}

.link::after {
    content: '';
    position: absolute;
    bottom: -2px;
    left: 0;
    width: 0;
    height: 2px;
    background: #007bff;
    transition: width 0.3s;
}

.link:hover::after {
    width: 100%;
}

/* Image zoom on hover */
.image-container {
    overflow: hidden;
    border-radius: 8px;
}

.image-container img {
    width: 100%;
    transition: transform 0.5s;
}

.image-container:hover img {
    transform: scale(1.1);
}

/* Smooth color mode transition */
body {
    background: white;
    color: black;
    transition: background-color 0.3s, color 0.3s;
}

body.dark-mode {
    background: #1a1a1a;
    color: white;
}

/* Accordion */
.accordion-item {
    border: 1px solid #ddd;
    border-radius: 4px;
    margin-bottom: 10px;
}

.accordion-header {
    padding: 15px;
    cursor: pointer;
    background: #f5f5f5;
    transition: background-color 0.3s;
}

.accordion-header:hover {
    background: #e0e0e0;
}

.accordion-content {
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.3s ease-out, padding 0.3s;
    padding: 0 15px;
}

.accordion-item.open .accordion-content {
    max-height: 500px;
    padding: 15px;
}

/* Navigation menu */
nav a {
    color: #333;
    text-decoration: none;
    padding: 10px 15px;
    display: inline-block;
    position: relative;
    transition: color 0.3s;
}

nav a::before {
    content: '';
    position: absolute;
    bottom: 0;
    left: 50%;
    width: 0;
    height: 2px;
    background: #007bff;
    transform: translateX(-50%);
    transition: width 0.3s;
}

nav a:hover {
    color: #007bff;
}

nav a:hover::before {
    width: 80%;
}

/* Form input focus */
.input {
    padding: 10px;
    border: 2px solid #ddd;
    border-radius: 4px;
    transition: border-color 0.3s, box-shadow 0.3s;
}

.input:focus {
    outline: none;
    border-color: #007bff;
    box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
}

/* Loading button */
.loading-button {
    padding: 10px 20px;
    background: #007bff;
    color: white;
    border: none;
    border-radius: 4px;
    min-width: 120px;
    transition: background-color 0.3s, opacity 0.3s;
}

.loading-button.loading {
    opacity: 0.6;
    pointer-events: none;
}

/* Toggle switch */
.switch {
    width: 50px;
    height: 26px;
    background: #ccc;
    border-radius: 13px;
    position: relative;
    cursor: pointer;
    transition: background-color 0.3s;
}

.switch::after {
    content: '';
    position: absolute;
    width: 20px;
    height: 20px;
    background: white;
    border-radius: 50%;
    top: 3px;
    left: 3px;
    transition: transform 0.3s;
}

.switch.active {
    background: #4caf50;
}

.switch.active::after {
    transform: translateX(24px);
}

/* Modal backdrop */
.modal-backdrop {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0,0,0,0);
    pointer-events: none;
    transition: background-color 0.3s;
}

.modal-backdrop.visible {
    background: rgba(0,0,0,0.5);
    pointer-events: auto;
}

/* Stagger transitions */
.list-item {
    opacity: 0;
    transform: translateY(20px);
    transition: opacity 0.3s, transform 0.3s;
}

.list-item:nth-child(1) { transition-delay: 0s; }
.list-item:nth-child(2) { transition-delay: 0.1s; }
.list-item:nth-child(3) { transition-delay: 0.2s; }
.list-item:nth-child(4) { transition-delay: 0.3s; }

.list-item.visible {
    opacity: 1;
    transform: translateY(0);
}

💡 Best Practices

/* 1. Use specific properties, not "all" */
/* Bad */
.element {
    transition: all 0.3s;
}

/* Good */
.element {
    transition: background-color 0.3s, transform 0.3s;
}

/* 2. Reasonable durations */
/* Too fast: < 150ms */
/* Too slow: > 1s */
/* Sweet spot: 200ms - 500ms */

/* 3. Use transform for smooth animations */
/* Bad (causes repaint) */
.box {
    transition: left 0.3s;
}

/* Good (GPU accelerated) */
.box {
    transition: transform 0.3s;
}

/* 4. Avoid transitioning expensive properties */
/* Expensive: width, height, top, left */
/* Cheap: transform, opacity */

/* 5. Provide feedback on interaction */
.button {
    transition: background-color 0.3s, transform 0.2s;
}

.button:hover {
    background-color: #0056b3;
}

.button:active {
    transform: scale(0.95);
}

/* 6. Consider reduced motion */
@media (prefers-reduced-motion: reduce) {
    * {
        transition-duration: 0.01ms !important;
    }
}

/* 7. Use will-change for complex transitions */
.complex {
    will-change: transform, opacity;
    transition: transform 0.3s, opacity 0.3s;
}

/* Remove after transition */
.complex:hover {
    will-change: auto;
}

🎯 Key Takeaways