
バリデーションアニメーションを実装したい……



入力エラーをより分かりやすく表示したい……
今回はこのようなお悩みをお持ちの方へ向けて
Web制作において必須のUI要素
バリデーションアニメーション
をご紹介します。
- シェイク効果(揺れる効果)
- パルス効果(脈動効果)
- スライド効果(スライドイン)
- フェード効果(フェードイン)
- カラー変化効果(色の変化)
- アイコン表示効果



特にフォームやログイン画面には、バリデーションアニメーションが非常に効果的です。この記事のコードをご活用いただきWeb制作の効率化に繋がれば何よりです。
なお、今回ご紹介するアニメーションはCSSとJavaScriptで実装できるので、基本的なコーディング知識があれば安心してご利用いただけます。
あわせて読みたい
バリデーションアニメーションとは
バリデーションアニメーションは、ユーザーの入力が正しくない場合に表示される視覚的なフィードバックを提供するアニメーション効果です。エラーの内容を分かりやすく伝え、ユーザビリティを向上させる効果的な手法です。
効果的な使用場面
適している場面
- フォーム入力フィールド
- ログイン・サインアップ画面
- パスワード入力
- メールアドレス入力
- 必須項目の入力チェック
避けるべき場面
- 過度に派手なアニメーション
- パフォーマンスを重視する場面
- アクセシビリティを重視する場面
実装方法の比較
アニメーション | 難易度 | 視覚的インパクト | パフォーマンス | ブラウザ対応 |
---|---|---|---|---|
シェイク効果 | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
パルス効果 | ⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
スライド効果 | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
フェード効果 | ⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
カラー変化効果 | ⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
アイコン表示効果 | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
シェイク効果
入力エラー時に要素が揺れるアニメーションです。
① デモ
See the Pen Untitled by ケケンタ (@lgshifbg-the-looper) on CodePen.
- 視覚的インパクトが高い
- エラーを明確に示す
- 注目を集める効果
② HTML
<div class="form-container">
<div class="input-group">
<input type="text" id="shake-input" class="shake-input" placeholder="お名前を入力">
<div class="error-message" id="shake-error">お名前を入力してください</div>
</div>
<div class="input-group">
<input type="email" id="shake-email" class="shake-input" placeholder="メールアドレスを入力">
<div class="error-message" id="shake-email-error">正しいメールアドレスを入力してください</div>
</div>
<div class="input-group">
<input type="password" id="shake-password" class="shake-input" placeholder="パスワードを入力">
<div class="error-message" id="shake-password-error">パスワードは8文字以上で入力してください</div>
</div>
<button type="button" id="shake-submit" class="submit-btn">送信</button>
</div>
③ CSS
/* フォームコンテナ */
.form-container {
max-width: 500px;
margin: 0 auto;
padding: 40px 20px;
font-family: 'Arial', sans-serif;
}
.input-group {
position: relative;
margin-bottom: 30px;
}
.shake-input {
width: 100%;
padding: 16px 12px;
border: 2px solid #e0e0e0;
border-radius: 8px;
font-size: 16px;
background: white;
transition: all 0.3s ease;
outline: none;
}
.shake-input:focus {
border-color: #667eea;
}
.shake-input.error {
border-color: #ff6b6b;
animation: shake 0.5s ease-in-out;
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); }
20%, 40%, 60%, 80% { transform: translateX(5px); }
}
.error-message {
color: #ff6b6b;
font-size: 14px;
margin-top: 8px;
opacity: 0;
transform: translateY(-10px);
transition: all 0.3s ease;
}
.error-message.show {
opacity: 1;
transform: translateY(0);
}
.submit-btn {
width: 100%;
padding: 16px;
background: #667eea;
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
cursor: pointer;
transition: all 0.3s ease;
}
.submit-btn:hover {
background: #5a6fd8;
}
④ JavaScript
document.addEventListener('DOMContentLoaded', function() {
const shakeInputs = document.querySelectorAll('.shake-input');
const submitBtn = document.getElementById('shake-submit');
// バリデーション関数
function validateInput(input) {
const value = input.value.trim();
const errorElement = input.parentElement.querySelector('.error-message');
// 入力値の検証
if (!value) {
showError(input, errorElement);
return false;
}
// メールアドレスの検証
if (input.type === 'email') {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(value)) {
showError(input, errorElement);
return false;
}
}
// パスワードの検証
if (input.type === 'password') {
if (value.length < 8) {
showError(input, errorElement);
return false;
}
}
hideError(input, errorElement);
return true;
}
// エラー表示
function showError(input, errorElement) {
input.classList.add('error');
errorElement.classList.add('show');
}
// エラー非表示
function hideError(input, errorElement) {
input.classList.remove('error');
errorElement.classList.remove('show');
}
// 入力時の検証
shakeInputs.forEach(input => {
input.addEventListener('blur', function() {
validateInput(this);
});
input.addEventListener('input', function() {
if (this.classList.contains('error')) {
validateInput(this);
}
});
});
// 送信ボタンクリック時の検証
submitBtn.addEventListener('click', function() {
let isValid = true;
shakeInputs.forEach(input => {
if (!validateInput(input)) {
isValid = false;
}
});
if (isValid) {
alert('送信しました!');
}
});
});
⑤ カスタマイズ例
/* シェイク速度の調整 */
@keyframes shake {
0%, 100% { transform: translateX(0); }
10%, 30%, 50%, 70%, 90% { transform: translateX(-10px); }
20%, 40%, 60%, 80% { transform: translateX(10px); }
}
/* シェイク強度の調整 */
.shake-input.error {
animation: shake 0.8s ease-in-out;
}
/* エラー色の変更 */
.shake-input.error {
border-color: #ff4757;
}
パルス効果
入力エラー時に脈動するアニメーションです。
① デモ
See the Pen Untitled by ケケンタ (@lgshifbg-the-looper) on CodePen.
- 動的な表現
- 視覚的インパクト
- 注目を集める効果
② HTML
<div class="form-container">
<div class="input-group">
<input type="text" id="pulse-input" class="pulse-input" placeholder="お名前を入力">
<div class="error-message" id="pulse-error">お名前を入力してください</div>
</div>
<div class="input-group">
<input type="email" id="pulse-email" class="pulse-input" placeholder="メールアドレスを入力">
<div class="error-message" id="pulse-email-error">正しいメールアドレスを入力してください</div>
</div>
<div class="input-group">
<input type="password" id="pulse-password" class="pulse-input" placeholder="パスワードを入力">
<div class="error-message" id="pulse-password-error">パスワードは8文字以上で入力してください</div>
</div>
<button type="button" id="pulse-submit" class="submit-btn">送信</button>
</div>
③ CSS
/* フォームコンテナ */
.form-container {
max-width: 500px;
margin: 0 auto;
padding: 40px 20px;
font-family: 'Arial', sans-serif;
}
.input-group {
position: relative;
margin-bottom: 30px;
}
.pulse-input {
width: 100%;
padding: 16px 12px;
border: 2px solid #e0e0e0;
border-radius: 8px;
font-size: 16px;
background: white;
transition: all 0.3s ease;
outline: none;
}
.pulse-input:focus {
border-color: #667eea;
}
.pulse-input.error {
border-color: #ff6b6b;
animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(255, 107, 107, 0.4);
}
70% {
box-shadow: 0 0 0 10px rgba(255, 107, 107, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(255, 107, 107, 0);
}
}
.error-message {
color: #ff6b6b;
font-size: 14px;
margin-top: 8px;
opacity: 0;
transform: translateY(-10px);
transition: all 0.3s ease;
}
.error-message.show {
opacity: 1;
transform: translateY(0);
}
.submit-btn {
width: 100%;
padding: 16px;
background: #667eea;
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
cursor: pointer;
transition: all 0.3s ease;
}
.submit-btn:hover {
background: #5a6fd8;
}
④ JavaScript
document.addEventListener('DOMContentLoaded', function() {
const pulseInputs = document.querySelectorAll('.pulse-input');
const submitBtn = document.getElementById('pulse-submit');
// バリデーション関数
function validateInput(input) {
const value = input.value.trim();
const errorElement = input.parentElement.querySelector('.error-message');
// 入力値の検証
if (!value) {
showError(input, errorElement);
return false;
}
// メールアドレスの検証
if (input.type === 'email') {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(value)) {
showError(input, errorElement);
return false;
}
}
// パスワードの検証
if (input.type === 'password') {
if (value.length < 8) {
showError(input, errorElement);
return false;
}
}
hideError(input, errorElement);
return true;
}
// エラー表示
function showError(input, errorElement) {
input.classList.add('error');
errorElement.classList.add('show');
}
// エラー非表示
function hideError(input, errorElement) {
input.classList.remove('error');
errorElement.classList.remove('show');
}
// 入力時の検証
pulseInputs.forEach(input => {
input.addEventListener('blur', function() {
validateInput(this);
});
input.addEventListener('input', function() {
if (this.classList.contains('error')) {
validateInput(this);
}
});
});
// 送信ボタンクリック時の検証
submitBtn.addEventListener('click', function() {
let isValid = true;
pulseInputs.forEach(input => {
if (!validateInput(input)) {
isValid = false;
}
});
if (isValid) {
alert('送信しました!');
}
});
});
⑤ カスタマイズ例
/* パルス速度の調整 */
.pulse-input.error {
animation: pulse 1s ease-in-out infinite;
}
/* パルス色の変更 */
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(255, 71, 87, 0.4);
}
70% {
box-shadow: 0 0 0 10px rgba(255, 71, 87, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(255, 71, 87, 0);
}
}
/* パルス強度の調整 */
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(255, 107, 107, 0.6);
}
70% {
box-shadow: 0 0 0 15px rgba(255, 107, 107, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(255, 107, 107, 0);
}
}
スライド効果
エラーメッセージがスライドインするアニメーションです。
① デモ
See the Pen バリデーションスライド効果 by ケケンタ (@lgshifbg-the-looper) on CodePen.
- スムーズな表示
- 視覚的フィードバック
- 洗練された表現
② HTML
<div class="form-container">
<div class="input-group">
<input type="text" id="slide-input" class="slide-input" placeholder="お名前を入力">
<div class="error-message" id="slide-error">お名前を入力してください</div>
</div>
<div class="input-group">
<input type="email" id="slide-email" class="slide-input" placeholder="メールアドレスを入力">
<div class="error-message" id="slide-email-error">正しいメールアドレスを入力してください</div>
</div>
<div class="input-group">
<input type="password" id="slide-password" class="slide-input" placeholder="パスワードを入力">
<div class="error-message" id="slide-password-error">パスワードは8文字以上で入力してください</div>
</div>
<button type="button" id="slide-submit" class="submit-btn">送信</button>
</div>
③ CSS
/* フォームコンテナ */
.form-container {
max-width: 500px;
margin: 0 auto;
padding: 40px 20px;
font-family: 'Arial', sans-serif;
}
.input-group {
position: relative;
margin-bottom: 30px;
}
.slide-input {
width: 100%;
padding: 16px 12px;
border: 2px solid #e0e0e0;
border-radius: 8px;
font-size: 16px;
background: white;
transition: all 0.3s ease;
outline: none;
}
.slide-input:focus {
border-color: #667eea;
}
.slide-input.error {
border-color: #ff6b6b;
}
.error-message {
color: #ff6b6b;
font-size: 14px;
margin-top: 8px;
opacity: 0;
transform: translateX(-20px);
transition: all 0.4s ease;
overflow: hidden;
max-height: 0;
}
.error-message.show {
opacity: 1;
transform: translateX(0);
max-height: 50px;
}
.submit-btn {
width: 100%;
padding: 16px;
background: #667eea;
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
cursor: pointer;
transition: all 0.3s ease;
}
.submit-btn:hover {
background: #5a6fd8;
}
④ JavaScript
document.addEventListener('DOMContentLoaded', function() {
const slideInputs = document.querySelectorAll('.slide-input');
const submitBtn = document.getElementById('slide-submit');
// バリデーション関数
function validateInput(input) {
const value = input.value.trim();
const errorElement = input.parentElement.querySelector('.error-message');
// 入力値の検証
if (!value) {
showError(input, errorElement);
return false;
}
// メールアドレスの検証
if (input.type === 'email') {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(value)) {
showError(input, errorElement);
return false;
}
}
// パスワードの検証
if (input.type === 'password') {
if (value.length < 8) {
showError(input, errorElement);
return false;
}
}
hideError(input, errorElement);
return true;
}
// エラー表示
function showError(input, errorElement) {
input.classList.add('error');
errorElement.classList.add('show');
}
// エラー非表示
function hideError(input, errorElement) {
input.classList.remove('error');
errorElement.classList.remove('show');
}
// 入力時の検証
slideInputs.forEach(input => {
input.addEventListener('blur', function() {
validateInput(this);
});
input.addEventListener('input', function() {
if (this.classList.contains('error')) {
validateInput(this);
}
});
});
// 送信ボタンクリック時の検証
submitBtn.addEventListener('click', function() {
let isValid = true;
slideInputs.forEach(input => {
if (!validateInput(input)) {
isValid = false;
}
});
if (isValid) {
alert('送信しました!');
}
});
});
⑤ カスタマイズ例
/* スライド速度の調整 */
.error-message {
transition: all 0.6s ease;
}
/* スライド方向の変更 */
.error-message {
transform: translateY(-20px);
}
.error-message.show {
transform: translateY(0);
}
/* スライド強度の調整 */
.error-message {
transform: translateX(-30px);
}
.error-message.show {
transform: translateX(0);
}
フェード効果
エラーメッセージがフェードインするアニメーションです。
① デモ
See the Pen バリデーションフェード効果 by ケケンタ (@lgshifbg-the-looper) on CodePen.
- シンプルで分かりやすい
- アクセシビリティが高い
- モダンな印象
② HTML
<div class="form-container">
<div class="input-group">
<input type="text" id="fade-input" class="fade-input" placeholder="お名前を入力">
<div class="error-message" id="fade-error">お名前を入力してください</div>
</div>
<div class="input-group">
<input type="email" id="fade-email" class="fade-input" placeholder="メールアドレスを入力">
<div class="error-message" id="fade-email-error">正しいメールアドレスを入力してください</div>
</div>
<div class="input-group">
<input type="password" id="fade-password" class="fade-input" placeholder="パスワードを入力">
<div class="error-message" id="fade-password-error">パスワードは8文字以上で入力してください</div>
</div>
<button type="button" id="fade-submit" class="submit-btn">送信</button>
</div>
③ CSS
/* フォームコンテナ */
.form-container {
max-width: 500px;
margin: 0 auto;
padding: 40px 20px;
font-family: 'Arial', sans-serif;
}
.input-group {
position: relative;
margin-bottom: 30px;
}
.fade-input {
width: 100%;
padding: 16px 12px;
border: 2px solid #e0e0e0;
border-radius: 8px;
font-size: 16px;
background: white;
transition: all 0.3s ease;
outline: none;
}
.fade-input:focus {
border-color: #667eea;
}
.fade-input.error {
border-color: #ff6b6b;
}
.error-message {
color: #ff6b6b;
font-size: 14px;
margin-top: 8px;
opacity: 0;
visibility: hidden;
transition: all 0.3s ease;
}
.error-message.show {
opacity: 1;
visibility: visible;
}
.submit-btn {
width: 100%;
padding: 16px;
background: #667eea;
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
cursor: pointer;
transition: all 0.3s ease;
}
.submit-btn:hover {
background: #5a6fd8;
}
④ JavaScript
document.addEventListener('DOMContentLoaded', function() {
const fadeInputs = document.querySelectorAll('.fade-input');
const submitBtn = document.getElementById('fade-submit');
// バリデーション関数
function validateInput(input) {
const value = input.value.trim();
const errorElement = input.parentElement.querySelector('.error-message');
// 入力値の検証
if (!value) {
showError(input, errorElement);
return false;
}
// メールアドレスの検証
if (input.type === 'email') {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(value)) {
showError(input, errorElement);
return false;
}
}
// パスワードの検証
if (input.type === 'password') {
if (value.length < 8) {
showError(input, errorElement);
return false;
}
}
hideError(input, errorElement);
return true;
}
// エラー表示
function showError(input, errorElement) {
input.classList.add('error');
errorElement.classList.add('show');
}
// エラー非表示
function hideError(input, errorElement) {
input.classList.remove('error');
errorElement.classList.remove('show');
}
// 入力時の検証
fadeInputs.forEach(input => {
input.addEventListener('blur', function() {
validateInput(this);
});
input.addEventListener('input', function() {
if (this.classList.contains('error')) {
validateInput(this);
}
});
});
// 送信ボタンクリック時の検証
submitBtn.addEventListener('click', function() {
let isValid = true;
fadeInputs.forEach(input => {
if (!validateInput(input)) {
isValid = false;
}
});
if (isValid) {
alert('送信しました!');
}
});
});
⑤ カスタマイズ例
/* フェード速度の調整 */
.error-message {
transition: all 0.5s ease;
}
/* フェード強度の調整 */
.error-message {
opacity: 0;
transform: scale(0.9);
}
.error-message.show {
opacity: 1;
transform: scale(1);
}
/* フェード方向の変更 */
.error-message {
opacity: 0;
transform: translateY(10px);
}
.error-message.show {
opacity: 1;
transform: translateY(0);
}
カラー変化効果
エラー時に色が変化するアニメーションです。
① デモ
See the Pen バリデーションカラー変化効果 by ケケンタ (@lgshifbg-the-looper) on CodePen.
- 直感的な状態表示
- 視覚的フィードバック
- カラフルな表現
② HTML
<div class="form-container">
<div class="input-group">
<input type="text" id="color-input" class="color-input" placeholder="お名前を入力">
<div class="error-message" id="color-error">お名前を入力してください</div>
</div>
<div class="input-group">
<input type="email" id="color-email" class="color-input" placeholder="メールアドレスを入力">
<div class="error-message" id="color-email-error">正しいメールアドレスを入力してください</div>
</div>
<div class="input-group">
<input type="password" id="color-password" class="color-input" placeholder="パスワードを入力">
<div class="error-message" id="color-password-error">パスワードは8文字以上で入力してください</div>
</div>
<button type="button" id="color-submit" class="submit-btn">送信</button>
</div>
③ CSS
/* フォームコンテナ */
.form-container {
max-width: 500px;
margin: 0 auto;
padding: 40px 20px;
font-family: 'Arial', sans-serif;
}
.input-group {
position: relative;
margin-bottom: 30px;
}
.color-input {
width: 100%;
padding: 16px 12px;
border: 2px solid #e0e0e0;
border-radius: 8px;
font-size: 16px;
background: white;
transition: all 0.3s ease;
outline: none;
}
.color-input:focus {
border-color: #667eea;
background: rgba(102, 126, 234, 0.05);
}
.color-input.error {
border-color: #ff6b6b;
background: rgba(255, 107, 107, 0.05);
color: #ff6b6b;
}
.color-input.success {
border-color: #51cf66;
background: rgba(81, 207, 102, 0.05);
color: #51cf66;
}
.error-message {
color: #ff6b6b;
font-size: 14px;
margin-top: 8px;
opacity: 0;
transform: translateY(-10px);
transition: all 0.3s ease;
}
.error-message.show {
opacity: 1;
transform: translateY(0);
}
.submit-btn {
width: 100%;
padding: 16px;
background: #667eea;
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
cursor: pointer;
transition: all 0.3s ease;
}
.submit-btn:hover {
background: #5a6fd8;
}
④ JavaScript
document.addEventListener('DOMContentLoaded', function() {
const colorInputs = document.querySelectorAll('.color-input');
const submitBtn = document.getElementById('color-submit');
// バリデーション関数
function validateInput(input) {
const value = input.value.trim();
const errorElement = input.parentElement.querySelector('.error-message');
// 入力値の検証
if (!value) {
showError(input, errorElement);
return false;
}
// メールアドレスの検証
if (input.type === 'email') {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(value)) {
showError(input, errorElement);
return false;
}
}
// パスワードの検証
if (input.type === 'password') {
if (value.length < 8) {
showError(input, errorElement);
return false;
}
}
showSuccess(input, errorElement);
return true;
}
// エラー表示
function showError(input, errorElement) {
input.classList.remove('success');
input.classList.add('error');
errorElement.classList.add('show');
}
// 成功表示
function showSuccess(input, errorElement) {
input.classList.remove('error');
input.classList.add('success');
errorElement.classList.remove('show');
}
// 入力時の検証
colorInputs.forEach(input => {
input.addEventListener('blur', function() {
validateInput(this);
});
input.addEventListener('input', function() {
if (this.classList.contains('error') || this.classList.contains('success')) {
validateInput(this);
}
});
});
// 送信ボタンクリック時の検証
submitBtn.addEventListener('click', function() {
let isValid = true;
colorInputs.forEach(input => {
if (!validateInput(input)) {
isValid = false;
}
});
if (isValid) {
alert('送信しました!');
}
});
});
⑤ カスタマイズ例
/* カラー変化速度の調整 */
.color-input {
transition: all 0.5s ease;
}
/* エラー色の変更 */
.color-input.error {
border-color: #ff4757;
background: rgba(255, 71, 87, 0.05);
color: #ff4757;
}
/* 成功色の変更 */
.color-input.success {
border-color: #2ed573;
background: rgba(46, 213, 115, 0.05);
color: #2ed573;
}
アイコン表示効果
エラー時にアイコンが表示されるアニメーションです。
① デモ
See the Pen Untitled by ケケンタ (@lgshifbg-the-looper) on CodePen.
- 右端配置で直感的な位置
- 円形の囲みでモダンな見た目
- テキストアイコンで軽量で分かりやすい
- 背景色とシャドウの動的変化
② HTML
<div class="form-container">
<div class="input-group">
<input type="text" id="icon-input" class="icon-input" placeholder="お名前を入力">
<div class="icon-wrapper">
<span class="error-icon">✕</span>
<span class="success-icon">✓</span>
</div>
<div class="error-message" id="icon-error">お名前を入力してください</div>
</div>
<div class="input-group">
<input type="email" id="icon-email" class="icon-input" placeholder="メールアドレスを入力">
<div class="icon-wrapper">
<span class="error-icon">✕</span>
<span class="success-icon">✓</span>
</div>
<div class="error-message" id="icon-email-error">正しいメールアドレスを入力してください</div>
</div>
<div class="input-group">
<input type="password" id="icon-password" class="icon-input" placeholder="パスワードを入力">
<div class="icon-wrapper">
<span class="error-icon">✕</span>
<span class="success-icon">✓</span>
</div>
<div class="error-message" id="icon-password-error">パスワードは8文字以上で入力してください</div>
</div>
<button type="button" id="icon-submit" class="submit-btn">送信</button>
</div>
③ CSS
/* フォームコンテナ */
.form-container {
max-width: 500px;
margin: 0 auto;
padding: 40px 20px;
font-family: 'Arial', sans-serif;
}
.input-group {
position: relative;
margin-bottom: 30px;
display: flex;
align-items: center;
}
.icon-wrapper {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
width: 36px;
height: 36px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(10px);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
}
.icon-input {
width: 100%;
padding: 16px 50px 16px 16px;
border: 2px solid #e0e0e0;
border-radius: 8px;
font-size: 16px;
background: white;
transition: all 0.3s ease;
outline: none;
}
.icon-input:focus {
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
.icon-input.error {
border-color: #ff6b6b;
box-shadow: 0 0 0 3px rgba(255, 107, 107, 0.1);
}
.icon-input.success {
border-color: #51cf66;
box-shadow: 0 0 0 3px rgba(81, 207, 102, 0.1);
}
.error-icon,
.success-icon {
font-size: 18px;
font-weight: bold;
opacity: 0;
visibility: hidden;
transform: scale(0.1) rotate(-180deg);
transition: all 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
color: white;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.error-icon.show {
opacity: 1;
visibility: visible;
transform: scale(1) rotate(0deg);
color: white;
}
.icon-wrapper.error {
background: #ff6b6b;
box-shadow: 0 2px 8px rgba(255, 107, 107, 0.3);
}
.success-icon.show {
opacity: 1;
visibility: visible;
transform: scale(1) rotate(0deg);
color: white;
}
.icon-wrapper.success {
background: #51cf66;
box-shadow: 0 2px 8px rgba(81, 207, 102, 0.3);
}
.error-message {
position: absolute;
left: 0;
top: 100%;
color: #ff6b6b;
font-size: 14px;
margin-top: 8px;
opacity: 0;
transform: translateY(-10px);
transition: all 0.3s ease;
}
.error-message.show {
opacity: 1;
transform: translateY(0);
}
.submit-btn {
width: 100%;
padding: 16px;
background: #667eea;
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
cursor: pointer;
transition: all 0.3s ease;
}
.submit-btn:hover {
background: #5a6fd8;
}
④ JavaScript
document.addEventListener('DOMContentLoaded', function() {
const iconInputs = document.querySelectorAll('.icon-input');
const submitBtn = document.getElementById('icon-submit');
// バリデーション関数
function validateInput(input) {
const value = input.value.trim();
const errorElement = input.parentElement.querySelector('.error-message');
const errorIcon = input.parentElement.querySelector('.error-icon');
const successIcon = input.parentElement.querySelector('.success-icon');
// 入力値の検証
if (!value) {
showError(input, errorElement, errorIcon, successIcon);
return false;
}
// メールアドレスの検証
if (input.type === 'email') {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(value)) {
showError(input, errorElement, errorIcon, successIcon);
return false;
}
}
// パスワードの検証
if (input.type === 'password') {
if (value.length < 8) {
showError(input, errorElement, errorIcon, successIcon);
return false;
}
}
showSuccess(input, errorElement, errorIcon, successIcon);
return true;
}
// エラー表示
function showError(input, errorElement, errorIcon, successIcon) {
const iconWrapper = input.parentElement.querySelector('.icon-wrapper');
input.classList.remove('success');
input.classList.add('error');
iconWrapper.classList.remove('success');
iconWrapper.classList.add('error');
errorElement.classList.add('show');
errorIcon.classList.add('show');
successIcon.classList.remove('show');
}
// 成功表示
function showSuccess(input, errorElement, errorIcon, successIcon) {
const iconWrapper = input.parentElement.querySelector('.icon-wrapper');
input.classList.remove('error');
input.classList.add('success');
iconWrapper.classList.remove('error');
iconWrapper.classList.add('success');
errorElement.classList.remove('show');
errorIcon.classList.remove('show');
successIcon.classList.add('show');
}
// 入力時の検証
iconInputs.forEach(input => {
input.addEventListener('blur', function() {
validateInput(this);
});
input.addEventListener('input', function() {
if (this.classList.contains('error') || this.classList.contains('success')) {
validateInput(this);
}
});
});
// 送信ボタンクリック時の検証
submitBtn.addEventListener('click', function() {
let isValid = true;
iconInputs.forEach(input => {
if (!validateInput(input)) {
isValid = false;
}
});
if (isValid) {
alert('送信しました!');
}
});
});
⑤ カスタマイズ例
/* アイコン表示速度の調整 */
.error-icon,
.success-icon {
transition: all 0.5s ease;
}
/* アイコンサイズの調整 */
.error-icon,
.success-icon {
font-size: 20px;
}
/* アイコン表示強度の調整 */
.error-icon.show,
.success-icon.show {
transform: scale(1.1) rotate(0deg);
}
/* アイコンの初期表示サイズ調整 */
.error-icon,
.success-icon {
transform: scale(0.1) rotate(-180deg);
}
まとめ
今回ご紹介した6種類のバリデーションアニメーションは、それぞれ異なる特徴と用途があります。
用途別おすすめ
- フォーム入力: シェイク効果・パルス効果
- ログイン画面: カラー変化効果・アイコン表示効果
- 重要度の高いエラー: シェイク効果・パルス効果
- 軽微なエラー: フェード効果・スライド効果
実装のポイント
- アクセシビリティを重視: エラー状態を明確に表示
- パフォーマンスを考慮: 軽量なアニメーション
- ブラウザ対応: 幅広いブラウザで動作するように
- ユーザビリティ: 直感的な操作を可能に



バリデーションアニメーションは、ユーザビリティとアクセシビリティを向上させる重要な要素です。この記事のコードを参考に、プロジェクトに最適なアニメーションを実装してください!
あわせて読みたい
もっと効率的にWeb制作を学びたい方へ
Web制作の学習は楽しいものですが、一人で進めていると「これで合っているのかな?」と不安になることもありますよね。
僕も独学でWeb制作を学んできましたが、今思うと「もっと早く知りたかった」と思うことがたくさんあります。
特に以下のような方は、一度プログラミングスクールの利用を検討してみることをおすすめします。
- 学習の方向性に迷いがある方
- 効率的にスキルを身につけたい方
- 転職や副業でWeb制作を活用したい方
- 挫折経験がある方
忍者CODEなら、業界最安値で24時間サポート付きの学習環境が整っています。


関連記事
アニメーション基礎知識
スクロールアニメーション
メニュー・ナビゲーション
\どれを読むか迷ったときのおすすめ‼/
タブ
\どれを読むか迷ったときのおすすめ‼/
フォーム・UI要素
ボタンホバーアニメーション
\どれを読むか迷ったときのおすすめ‼/
コメント