{}const=>[]async()letfn</>var
DevelopmentMobile

How to make "like Tinkoff/Yandex": animations and micro-interactions that immediately make the app "expensive"

You don't need to be a designer or know 3D. Simple CSS animations and JavaScript tricks that immediately raise the level of your application. Step-by-step guide with code and explanations - from buttons to modal windows.

К

Kodik

Author

6 min read

Have you noticed how the Tinkoff, Yandex or Alfa-Bank apps are just pleasant to use? Buttons respond to clicks, elements appear smoothly, downloads do not annoy, but on the contrary — they are pleasing to the eye. This is not magic or an army of designers. This is a set of specific techniques that you can master as well.

Why is this important at all?

The user will not say: "Wow, there is a transition with cubic-bezier!". But he will say: "What a nice application" or "It looks kind of cheap." High-quality animations work on a subconscious level:

  • They create a sense of speed - even if the server is slow

  • Give feedback — the user understands that their action has been taken into account

  • Reduce cognitive load — smooth transitions help the brain understand what is happening

  • They inspire confidence — details show that the team cares about the product

🔥 100,000+ students already with us

Tired of reading theory?
Time to code!

Kodik — an app where you learn to code through practice. AI mentor, interactive lessons, real projects.

🤖 AI 24/7
🎓 Certificates
💰 Free
🚀 Start learning
Joined today

1. Skeletons instead of spinners

What's wrong with the spinners?

The spinning circle does not provide any information. The user does not know how long to wait and what is being loaded.

What they do in Tinkoff:

They show the "ghost" of future content — gray blocks in place of text, pictures, buttons. This is called a skeleton screen or skeleton.

.skeleton {
  background: linear-gradient(
    90deg,
    #f0f0f0 25%,
    #e0e0e0 50%,
    #f0f0f0 75%
  );
  background-size: 200% 100%;
  animation: loading 1.5s infinite;
  border-radius: 4px;
}

@keyframes loading {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}

Why it works:

The brain perceives the skeleton as "the content is almost loaded", and not "you have to wait for an unknown amount of time". According to research, users estimate the loading time with skeletons to be 30-40% faster than with spinners.

2. Tactile response to actions

Button click effect:

When you press a button in the Yandex app, it "sinks" a little. This simulates a physical button.

.button {
  background: #ffdd2d;
  border: none;
  padding: 12px 24px;
  border-radius: 8px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.button:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15);
}

.button:active {
  transform: translateY(0);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

Ripple effect (wave):

When you click, a wave diverges from the point of click. This is a Material Design feature, but everyone uses it.

function createRipple(event) {
  const button = event.currentTarget;
  const circle = document.createElement('span');
  const diameter = Math.max(button.clientWidth, button.clientHeight);
  const radius = diameter / 2;

  circle.style.width = circle.style.height = `${diameter}px`;
  circle.style.left = `${event.clientX - button.offsetLeft - radius}px`;
  circle.style.top = `${event.clientY - button.offsetTop - radius}px`;
  circle.classList.add('ripple');

  const ripple = button.getElementsByClassName('ripple')[0];
  if (ripple) {
    ripple.remove();
  }

  button.appendChild(circle);
}

3. Smart transitions between states

Bad:

Content just disappears and reappears. Quickly. Cheaply.

Good:

We use smooth transitions with transform and opacity.

.fade-enter {
  opacity: 0;
  transform: translateY(10px);
}

.fade-enter-active {
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.fade-enter-to {
  opacity: 1;
  transform: translateY(0);
}

Golden rule: Any change to the DOM must be animated. No sudden appearances/disappearances.

4. Micro-animation of forms

When focusing on input:

.input {
  border: 2px solid #e0e0e0;
  padding: 12px;
  width: 100%;
  transition: all 0.2s ease;
  outline: none;
}

.input:focus {
  border-color: #ffdd2d;
  box-shadow: 0 0 0 4px rgba(255, 221, 45, 0.1);
}

.input-label {
  position: absolute;
  left: 12px;
  top: 12px;
  color: #999;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  pointer-events: none;
}

.input:focus + .input-label,
.input:not(:placeholder-shown) + .input-label {
  top: -8px;
  left: 8px;
  font-size: 12px;
  background: white;
  padding: 0 4px;
  color: #ffdd2d;
}

Validation with animation:

.input-error {
  border-color: #ff3333;
  animation: shake 0.4s;
}

@keyframes shake {
  0%, 100% { transform: translateX(0); }
  10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); }
  20%, 40%, 60%, 80% { transform: translateX(5px); }
}

5. Progress bars that don't drive you crazy

Bad progress bar: just moving. Boring.

Good progress bar: smooth, with a slight glow, shows specific stages.

.progress-bar {
  width: 100%;
  height: 6px;
  background: #f0f0f0;
  border-radius: 10px;
  overflow: hidden;
  position: relative;
}

.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #ffdd2d, #ffc700);
  border-radius: 10px;
  transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  box-shadow: 0 0 10px rgba(255, 221, 45, 0.5);
}

6. Modal windows with smart appearance

Incorrect: the window just pops up.

Correct: the background darkens, the window appears with a slight scaling and movement from bottom to top.

.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.3s ease;
  pointer-events: none;
}

.modal-overlay.active {
  background: rgba(0, 0, 0, 0.5);
  pointer-events: all;
}

.modal {
  background: white;
  border-radius: 16px;
  padding: 24px;
  max-width: 500px;
  width: 90%;
  transform: scale(0.9) translateY(20px);
  opacity: 0;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.modal-overlay.active .modal {
  transform: scale(1) translateY(0);
  opacity: 1;
}

7. Cards with hover effects

Cards of goods, posts, projects — they should respond to hovering:

.card {
  background: white;
  border-radius: 12px;
  padding: 20px;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

.card:hover {
  transform: translateY(-4px);
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
}

.card img {
  transition: transform 0.3s ease;
}

.card:hover img {
  transform: scale(1.05);
}

8. Loading indicators for actions

When the user clicks "Send", the button should show that the process is in progress:

.submit-button {
  position: relative;
  min-width: 120px;
  transition: all 0.3s ease;
}

.submit-button.loading {
  pointer-events: none;
}

.spinner {
  width: 20px;
  height: 20px;
  animation: rotate 1s linear infinite;
}

@keyframes rotate {
  100% { transform: rotate(360deg); }
}

9. Toasts and notifications

Principles:

  • Appear on the side (top right or left)

  • Smoothly enter

  • Automatically disappear after 3-5 seconds

  • Can be closed manually

.toast {
  position: fixed;
  top: 20px;
  right: -300px;
  background: white;
  padding: 16px 20px;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  min-width: 250px;
  transition: right 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.toast.show {
  right: 20px;
}

10. Important Animation Principles

Timing functions:

Don't just use ease or linear. Explore cubic-bezier:

  • ease-in-out - smoothly accelerates and decelerates

  • cubic-bezier(0.4, 0, 0.2, 1) — Material Design easing, very pleasant

  • cubic-bezier(0.25, 0.46, 0.45, 0.94) — easeOutQuad for fast animations

Duration:

  • Micro-interactions (hover, clicks): 100-200ms

  • Transitions between states: 200-300ms

  • Modal windows, drawers: 300-400ms

  • Page animations: 400-600ms

More than 600ms is already too slow.

60 FPS rule:

Animate only the properties that do not cause reflow:

  • transform, opacity

  • width, height, top, left, margin

Conclusion

High-quality animations are not about complexity, but about details. You don't need to study 3D or physics. You just need to:

  1. Add smoothness to everything

  2. Give feedback on actions

  3. Use the correct timing functions

  4. Be consistent

Start with one button. Make it pleasant. Then another one. Then the forms. Then the cards. In a month, your app will look like a million.

All this and much more can be studied in Codice - in detail, with practical tasks and real examples. We analyze not only the theory, but also show how it all works in real projects.

And if you need support, have questions, or want to discuss the code, we have huge active community in Telegram channel! More than 2000 developers who will always help, advise and support.

👉 Start learning in Kodik 🔥 Join Telegram

🎯Stop procrastinating

Liked the article?
Time to practice!

In Kodik, you don't just read — you write code immediately. Theory + practice = real skills.

Instant practice
🧠AI explains code
🏆Certificate

No registration • No card