Как сверстать стрелку вокруг поля ввода?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Верстка стрелки вокруг поля ввода
Создание стрелки вокруг поля ввода - это интересная и распространенная задача UI дизайна. Есть множество способов реализовать это, от простых CSS решений до сложных SVG анимаций. Рассмотрю самые практичные и эффективные варианты.
Способ 1: Border с CSS (самый простой)
Самый базовый и эффективный способ - использовать border и border-radius:
export function ArrowInput() {
const [value, setValue] = useState('');
return (
<div className="relative inline-block">
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="Enter text..."
className="px-4 py-2 pr-10 border-2 border-blue-500 rounded-lg outline-none focus:border-blue-700 transition-colors"
/>
{/* Стрелка вправо */}
<span className="absolute right-3 top-1/2 transform -translate-y-1/2 text-blue-500">
→
</span>
</div>
);
}
Способ 2: Стрелка с использованием ::before и ::after
Создаем стрелку чистым CSS без использования иконок:
.input-with-arrow {
position: relative;
display: inline-block;
}
.input-with-arrow input {
padding-right: 40px;
padding-left: 15px;
padding-top: 8px;
padding-bottom: 8px;
border: 2px solid #3b82f6;
border-radius: 8px;
font-size: 16px;
transition: border-color 0.3s;
}
.input-with-arrow input:focus {
outline: none;
border-color: #1e40af;
}
/* Создаем стрелку с ::after */
.input-with-arrow::after {
content: '';
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
width: 0;
height: 0;
border-left: 6px solid #3b82f6;
border-top: 4px solid transparent;
border-bottom: 4px solid transparent;
}
.input-with-arrow input:focus ~ ::after {
border-left-color: #1e40af;
}
Способ 3: SVG стрелка (более гибкое решение)
SVG дает больше контроля над внешним видом:
export function InputWithSVGArrow() {
const [value, setValue] = useState('');
return (
<div className="relative inline-block w-full max-w-md">
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="Enter text..."
className="w-full px-4 py-3 pr-12 border-2 border-blue-500 rounded-lg focus:outline-none focus:border-blue-700"
/>
<svg
className="absolute right-3 top-1/2 transform -translate-y-1/2 w-6 h-6 text-blue-500 pointer-events-none"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
{/* Простая стрелка вправо */}
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M9 5l7 7-7 7"
/>
</svg>
</div>
);
}
Способ 4: Стрелка по периметру поля (более сложная)
Если нужна стрелка, проходящая вокруг контура поля:
export function InputWithBorderArrow() {
const [focused, setFocused] = useState(false);
return (
<div className={`
relative w-full max-w-md
${focused ? 'border-4' : 'border-2'}
border-transparent
transition-all duration-300
rounded-2xl
padding-1
${focused ? 'border-blue-500' : 'border-gray-300'}
`}>
{/* Фон с градиентом для стрелки */}
<div className="absolute inset-0 rounded-2xl bg-gradient-to-r from-blue-500 via-blue-400 to-blue-500" />
{/* Контент */}
<div className="relative bg-white rounded-2xl">
<input
type="text"
onFocus={() => setFocused(true)}
onBlur={() => setFocused(false)}
placeholder="Hover or focus..."
className="w-full px-4 py-3 rounded-2xl outline-none"
/>
{/* SVG стрелка в углу */}
<svg
className="absolute -top-2 -right-2 w-8 h-8 text-blue-500"
fill="currentColor"
viewBox="0 0 24 24"
>
<path d="M7 14l5-5 5 5z" />
</svg>
</div>
</div>
);
}
Способ 5: Анимированная стрелка с rotation
Стрелка, которая вращается при фокусе:
export function AnimatedArrowInput() {
const [focused, setFocused] = useState(false);
return (
<div className="relative inline-block w-full max-w-md">
<input
type="text"
onFocus={() => setFocused(true)}
onBlur={() => setFocused(false)}
placeholder="Focus to see animation..."
className="w-full px-4 py-3 pr-12 border-2 border-blue-500 rounded-lg focus:outline-none focus:border-blue-700"
/>
<svg
className={`
absolute right-3 top-1/2 transform -translate-y-1/2
w-6 h-6 text-blue-500
transition-transform duration-300
${focused ? 'rotate-90' : 'rotate-0'}
`}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M13 7l5 5m0 0l-5 5m5-5H6"
/>
</svg>
</div>
);
}
Способ 6: Стрелка вокруг поля с border-image
Использование border-image для создания декоративной стрелки:
.input-rounded-arrow {
position: relative;
width: 100%;
max-width: 400px;
padding: 8px 0;
}
.input-rounded-arrow input {
width: 100%;
padding: 12px 16px;
border: 3px solid transparent;
border-radius: 12px;
background-image: linear-gradient(white, white),
conic-gradient(from 0deg, #3b82f6, #3b82f6);
background-origin: padding-box, border-box;
background-clip: padding-box, border-box;
font-size: 16px;
transition: background-image 0.3s;
}
.input-rounded-arrow input:focus {
outline: none;
background-image: linear-gradient(white, white),
conic-gradient(
from 0deg,
#1e40af,
#3b82f6,
#1e40af,
#1e40af
);
}
/* Стрелка в правом углу */
.input-rounded-arrow::after {
content: '';
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
width: 6px;
height: 6px;
border-right: 2px solid #3b82f6;
border-top: 2px solid #3b82f6;
transform: translateY(-50%) rotate(45deg);
transition: border-color 0.3s;
}
.input-rounded-arrow input:focus ~ ::after {
border-color: #1e40af;
}
Способ 7: Полная обертка со стрелками в углах
Создание эффекта, где стрелки находятся в углах поля:
export function InputWithCornerArrows() {
return (
<div className="relative w-full max-w-md">
<div className="relative border-2 border-blue-500 rounded-lg p-0.5">
{/* Верхняя левая стрелка */}
<div className="absolute -top-2 -left-2 text-blue-500 text-lg">↖</div>
{/* Верхняя правая стрелка */}
<div className="absolute -top-2 -right-2 text-blue-500 text-lg">↗</div>
{/* Нижняя левая стрелка */}
<div className="absolute -bottom-2 -left-2 text-blue-500 text-lg">↙</div>
{/* Нижняя правая стрелка */}
<div className="absolute -bottom-2 -right-2 text-blue-500 text-lg">↘</div>
<input
type="text"
placeholder="Input with corner arrows"
className="w-full px-4 py-3 outline-none bg-transparent"
/>
</div>
</div>
);
}
Способ 8: Стрелка с пульсирующей анимацией
Красивый эффект с пульсированием:
export function PulsingArrowInput() {
const [focused, setFocused] = useState(false);
return (
<style>{`
@keyframes pulse-arrow {
0%, 100% {
opacity: 1;
transform: translateY(-50%);
}
50% {
opacity: 0.6;
transform: translateY(-50%) translateX(4px);
}
}
.arrow-pulse {
animation: pulse-arrow 1s ease-in-out infinite;
}
`}</style>
<div className="relative w-full max-w-md">
<input
type="text"
onFocus={() => setFocused(true)}
onBlur={() => setFocused(false)}
placeholder="Focus to see pulsing arrow..."
className="w-full px-4 py-3 pr-12 border-2 border-blue-500 rounded-lg focus:outline-none focus:border-blue-700"
/>
<svg
className={`
absolute right-3 top-1/2 w-6 h-6 text-blue-500 pointer-events-none
${focused ? 'arrow-pulse' : ''}
`}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M13 7l5 5m0 0l-5 5m5-5H6"
/>
</svg>
</div>
);
}
Способ 9: Полный компонент с Tailwind и Heroicons
import { ChevronRightIcon } from '@heroicons/react/24/outline';
import { useState } from 'react';
export function ModernArrowInput({
placeholder = 'Search...',
onSubmit = () => {}
}) {
const [value, setValue] = useState('');
const [focused, setFocused] = useState(false);
const handleKeyPress = (e) => {
if (e.key === 'Enter') {
onSubmit(value);
}
};
return (
<div className={`
relative w-full max-w-xl
transition-all duration-300
${focused ? 'ring-2 ring-blue-400' : ''}
`}>
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
onFocus={() => setFocused(true)}
onBlur={() => setFocused(false)}
onKeyPress={handleKeyPress}
placeholder={placeholder}
className={`
w-full px-5 py-3 pr-14
border-2 rounded-xl
transition-all duration-300
${focused
? 'border-blue-500 shadow-lg'
: 'border-gray-300 hover:border-gray-400'
}
focus:outline-none
bg-white
text-base
`}
/>
{/* Стрелка с фоном при значении */}
{value && (
<button
onClick={() => onSubmit(value)}
className={`
absolute right-2 top-1/2 -translate-y-1/2
p-2 rounded-lg
transition-all duration-300
${focused
? 'bg-blue-100 text-blue-600 hover:bg-blue-200'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
}
`}
>
<ChevronRightIcon className="w-5 h-5" />
</button>
)}
</div>
);
}
Рекомендации
| Способ | Сложность | Производительность | Когда использовать |
|---|---|---|---|
| Text символ (→) | Очень низкая | Отличная | Простые поля, быстрый прототип |
| CSS ::before/::after | Низкая | Отличная | Стрелка в углу/краю |
| SVG | Средняя | Хорошая | Кастомные формы, анимации |
| Border-image | Средняя | Хорошая | Декоративные границы |
| Углы стрелок | Средняя | Хорошая | Специальные дизайны |
| Анимация | Средняя | Хорошая | Интерактивные эффекты |
| Компонент с иконкой | Низкая | Отличная | Production код с Tailwind |
Итоги
Для быстрого решения используй текстовый символ или SVG иконку справа. Для специальных эффектов - CSS ::after с трансформацией или анимацией. Выбор зависит от дизайн-требований и производительности.