API صفحه کلید مجازی

استاد چیدمان
آیا با مشکلی مواجه شده اید که یک مورد ثابت در دستگاه تلفن همراه وجود داشته باشد و هنگامی که صفحه کلید فعال است، آن مورد در زیر صفحه کلید پنهان می شود؟
این رفتار پیش فرض در وب برای سال ها بوده است. در این مقاله، مشکل را بررسی میکنیم، چرا اتفاق میافتد، و چگونه میتوانیم امروز آن را با Virtual Keyboard API حل کنیم.
بیایید شیرجه بزنیم
مشکل
قبل از پرداختن به جزئیات دقیق، اجازه دهید به یک مثال نگاه کنیم. این یک رابط کاربری است که دارای موارد زیر است:
- هدر چسبنده
- دکمه اکشن شناور چسبنده (FAB)

هنگامی که کاربر بر روی تایپ تمرکز می کند، صفحه کلید مجازی نمایش داده می شود. آیا می توانید پیش بینی کنید چه اتفاقی خواهد افتاد؟
مرورگر به سمت بالا حرکت می کند تا ورودی بالای صفحه کلید را ایجاد کند، و بنابراین هدر چسبنده و دکمه شناور ناپدید می شوند.
شبیه موارد زیر است:

این رفتار پیش فرض در مرورگرهای موبایل به طور کلی است. از منظر UX، پنهان کردن بخشهایی از رابط کاربری، بهویژه آن بخشهایی که مربوط به عملکرد فعلی من در هنگام فعال بودن صفحهکلید است، میتواند آزاردهنده باشد.
آنچه در پشت صحنه اتفاق می افتد چیزی شبیه به شکل زیر است.

از نقطه نظر فنی، قسمت قابل مشاهده نامیده می شود نمای بصری، و قسمت های پنهان همراه با آنچه در حال حاضر قابل مشاهده است است پنجره نمای چیدمان.

مشکل اصلی این است که وقتی صفحه کلید مجازی فعال است، پنجره بصری کوچک می شود.
رفع محتوای پنهان زیر صفحه کلید با API صفحه کلید مجازی
به لطف Virtual Keyboard API، ما می توانیم هر دو را تعریف کنیم بصری و چیدمان پنجره ها مسطح هستند با این کار میتوانیم موقعیت و ابعاد صفحهکلید را با متغیرهای محیط CSS زیر شناسایی کنیم:
- صفحه کلید-درج-بالا
- صفحه کلید-inset-راست
- صفحه کلید-درج-پایین
- صفحه کلید-inset-left
- صفحه کلید با عرض درج شده
- ارتفاع درج صفحه کلید

با استفاده از متغیرهای بالا، می توانیم در زمانی که صفحه کلید مجازی فعال است، چیدمان را تغییر دهیم.
پشتیبانی از مرورگر
از زمان نگارش این مقاله، VirtualKeyboard API فقط در Chrome for Android پشتیبانی میشود.
در بخش بعدی، به چند مثال می پردازم و از مواردی استفاده می کنم که این می تواند مفید باشد.
فعال کردن API صفحه کلید مجازی
این API به طور پیش فرض در دسترس نیست. برای فعال کردن آن باید از جاوا اسکریپت استفاده کنیم.
موارد زیر را ببینید:
if ("virtualKeyboard" in navigator) {
navigator.virtualKeyboard.overlaysContent = true
}
من این را کمی عجیب دیدم. استفاده از جاوا اسکریپت برای فعال کردن چنین رفتاری. من با براموس در مقاله اش در این زمینه موافقم. او پیشنهاد کرد از متا تگ مانند زیر استفاده کنید:
meta
name="viewport"
content="width=device-width, initial-scale=1.0, virtual-keyboard=overlays-content"
/>
یا یک ویژگی CSS:
html {
virtual-keyboard: overlays-content;
}
به روز رسانی: 2 آگوست 2023
برامز با مهربانی متذکر شد که یک مورد جدید وجود دارد interactive-widget در متا تگ viewport که به تغییر رفتار تغییر اندازه کمک می کند.
برای جزئیات بیشتر به MDN مراجعه کنید.
با استفاده از VirtualKeyboard API
اقدامات زیر ثابت شده است
در یک نمای کوچکتر، ممکن است نیاز داشته باشید که یک دکمه فراخوان یا پاورقی داشته باشید که به پایین رابط کاربری متصل است.
شکل زیر را در نظر بگیرید که در آن یک دکمه CTA داریم که در پایین ثابت شده است. در وسط صفحه یک فیلد ورودی وجود دارد.

هنگامی که فیلد ورودی فعال است، دکمه پرداخت زیر صفحه کلید مجازی خواهد بود، بنابراین پنهان می شود.

ما می توانیم این مشکل را به راحتی با API صفحه کلید مجازی حل کنیم.
input {
font-size: 16px;
}
.cta {
bottom: env(keyboard-inset-height, 0);
}
در دستگاه های تلفن همراه ارزش bottom برابر با ارتفاع صفحه کلید خواهد بود، بنابراین دکمه CTA با آن مقدار جبران می شود. اگر مرورگر از API پشتیبانی نمی کند، به طور پیش فرض این کار را انجام می دهد zero.

ممکن است در مورد کاهش فضا به دلیل داشتن قسمت بالایی و پایینی ثابت تعجب کنید. اگر فضای عمودی کافی باشد، میتوانیم از کوئریهای رسانه عمودی برای نمایش هدر استفاده کنیم.
اسکرول کردن به انتهای صفحه امکان پذیر نیست
هنگامی که یک مورد با position: fixed در انتهای نمای طرح بندی معمولاً a اضافه می کنیم padding-bottom برای جابجایی صفحه و اجازه دادن به کاربر برای حرکت به انتهای آن.

body {
--cta-height: 60px;
padding-bottom: var(--cta-height);
}
.cta {
bottom: env(keyboard-inset-height, 0);
}
را padding-bottom باید مقداری باشد که مساوی یا بزرگتر از ارتفاع ثابت عنصر باشد.
باحال، درسته؟ وقتی صفحه کلید مجازی را روشن می کنیم چه اتفاقی می افتد؟ بیایید نگاهی بیندازیم.
شکل زیر را در نظر بگیرید:

وقتی صفحه کلید مجازی فعال است، padding-bottom یک مقدار با ارتفاع عنصر ثابت کافی نیست. باید یک صفحه کلید به آن اضافه کنیم.
برای تجسم بهتر مشکل، در اینجا یک ویدیو وجود دارد:
برای رفع این مشکل، باید تشخیص دهیم که ورودی چه زمانی متمرکز است و تغییر می کند padding-bottom بر اساس آن
body:has(input:focus) {
padding-bottom: calc(
var(--cta-height) + env(keyboard-inset-height, 0)
);
}
شاید از خود بپرسید که در دسکتاپ چه اتفاقی خواهد افتاد؟ سوال خوبیه را env() به عقب خواهد افتاد 0 و مجموع منجر به ارزش می شود var(--cta-height).
دکمه اکشن شناور
در این مثال، یک دکمه اکشن شناور داریم که در گوشه سمت راست پایین صفحه قرار دارد.

هنگامی که صفحه کلید فعال است، دکمه شناور باید روی آن قرار بگیرد. مانند مثال اول، دکمه شناور زیر صفحه کلید خواهد بود.
برای رفع این مشکل می توانیم استفاده کنیم env(keyboard-inset-height) ارزش
بیایید راه حل را مرور کنیم:
.fab {
bottom: calc(1rem + env(keyboard-inset-height, 0rem));
}
من استفاده کردم 1rem به علاوه ارتفاع صفحه کلید برای جلوگیری از داشتن دکمه شناور مستقیماً در بالای صفحه کلید.
با توابع مقایسه CSS، توجه به این نکته مهم است که استفاده از یک عدد بدون واحد برای مقدار بازگشتی در داخل env() همه چیز را در سافاری خراب می کند. باید واحد را اضافه کنیم rem.

از مقدار متفاوتی برای دسکتاپ استفاده کنید
فرض کنید می خواهیم دکمه شناور را کمی بیشتر در مرورگرهای دسکتاپ جابجا کنیم، چگونه می توانیم این کار را انجام دهیم؟ خب داشتم فکر میکردم استفاده کنم max() عملکرد را مقایسه کنید و کار کرد.
.fab {
bottom: max(2rem, 1rem + env(keyboard-inset-height, 0rem));
}
در اینجا نحوه کار آن آمده است:
- تابع مقایسه دو مقدار را با هم مقایسه می کند. از آنجایی که
env(keyboard-inset-height)ارزیابی می کندzeroدر دسکتاپ حداکثر مقدار است2rem. - در دستگاه های تلفن همراه، حداکثر مقدار دوم است.

برای آشنایی بیشتر با توابع مقایسه CSS، می توانید این مقاله را مطالعه کنید.
طرح چت
من از مثال این مقاله توسط توماس اشتاینر الهام گرفتم و می خواستم به شما نشان دهم که چگونه کار می کند.
شکل زیر را در نظر بگیرید:

هنگامی که صفحه کلید فعال است، هدر و کادر پیام پنهان می شوند. می توانیم استفاده کنیم env(keyboard-inset-height) به عنوان یک ارزش برای grid-row دارایی
.layout {
display: grid;
grid-template-rows: auto minmax(0, 1fr) auto env(keyboard-inset-height, 0);
height: 100dvh;
}
در اینجا به نظر می رسد با اصلاح بالا:

از API صفحه کلید مجازی هوشمندانه استفاده کنید
صفحه کلید مجازی فقط باید در مواقع ضروری استفاده شود. استفاده از آن در هر زمینه ای می تواند مشکلاتی را ایجاد کند. بله درست خواندید

بیایید یک مثال ساده بزنیم. ما یک صفحه تماس با محتوای طولانی و فرم های انتخابی داریم. اگر صفحهکلید مجازی را روی محتوای صفحه قرار دهیم، امکان پیمایش به انتهای فرم وجود نخواهد داشت.
در این مورد، من صفحه کلید را برای پوشاندن محتوا توصیه نمی کنم. عاقلانه از آن استفاده کنید.
ویدیوی زیر را تماشا کنید تا متوجه مشکل شوید:
نسخه ی نمایشی کدپن
استفاده از توابع مقایسه با API صفحه کلید مجازی
تغییر یک دکمه بر اساس قابلیت مشاهده صفحه کلید مجازی
این ممکن است یک مورد یا مثال بی فایده باشد، اما جالب است که ببینید وقتی یک ویژگی به طور کامل از پتانسیل خود استفاده می کند چه اتفاقی می افتد.

فکر کردم چرا ویژگی های مقایسه CSS و صفحه کلید مجازی را با هم ترکیب نکنیم env ارزش ها؟ من این کار را کردم و نتیجه داد.
ویدیوی زیر را ببینید:
چگونه این اتفاق می افتد؟ اینجاست:
.fab {
--size: 4rem;
position: fixed;
right: min(1rem, 100vw - env(keyboard-inset-width, 0rem));
bottom: max(1rem, env(keyboard-inset-height, 0rem));
width: max(var(--size), env(keyboard-inset-width, 0rem));
height: var(--size);
border-radius: max(
0px,
min(50px, 100% - env(keyboard-inset-width))
);
}
این هم روی دسکتاپ و هم روی موبایل کار می کند. این چیزی است که اتفاق می افتد:
- را
rightارزش هر دو خواهد بود1remیاzeroاولی برای دسکتاپ و دومی برای موبایل (زمانی که صفحه کلید فعال است).100vwدر این حالت برابر با عرض صفحه کلید است، بنابراین نتیجه صفر است.min(1rem, 0). - کمترین مقدار هر دو خواهد بود
1remیا ارتفاع صفحه کلید - عرض اندازه دسکتاپ برابر است با
--sizeمتغیر است، و در موبایل تمام عرض را می گیرد، پس چراenv(keyboard-inset-width, 0)استفاده می شود. - و در نهایت، در
border-radiusمی تواند هر دو باشد50pxیا0.
تمیز، درست است؟ من هرگز انتظار نداشتم که چنین نسخه ی نمایشی ارائه کنم. به نظر شما ممکن است مفید باشد؟ من برای دیدن آنچه شما می سازید هیجان زده هستم.
نسخه ی نمایشی کدپن
فرم و پیمایش پست های لینکدین
مثالی که من پتانسیل خوبی برای اجرای API صفحه کلید مجازی دیدم، نحوه نمایش فرم پست و پیمایش برای یک پست لینکدین است.
شکل زیر را در نظر بگیرید:

فرم پست و پیمایش در پایین ثابت شده است. هنگامی که کاربر فیلد ورودی را فعال می کند، به نظر می رسد:

توجه کنید که چگونه املاک و مستغلات عمودی بسیار کوچک است. چه کار کنم؟ با ترکیب توابع مقایسه و API صفحه کلید مجازی، میتوانیم هنگام نمایش صفحهکلید، ناوبری را پنهان کنیم.
در اینجا CSS است که این کار را انجام می دهد.
.post-form,
.nav {
position: fixed;
left: 0;
right: 0;
}
.post-form {
bottom: max(48px, env(keyboard-inset-height, 0px));
}
.nav {
bottom: max(0px, env(keyboard-inset-height, 0) - 100px);
}
نگران نباشید، ذره ذره توضیح خواهم داد.
فرم انتشار
در حالت پیش فرض، فرم با افست می شود 48px از پایین در این حالت قسمت دوم از max() تابع غیر فعال است

هنگامی که صفحه کلید فعال است، قسمت دوم از max() نیز کار خواهد کرد bottom مقدار به ارتفاع صفحه کلید تبدیل می شود.

ناوبری
ناوبری در قرار گرفته است bottom: 0. قسمت اول از max() تابع چیزی است که در حال حاضر فعال است.

وقتی صفحه کلید فعال است، پیمایش را به زیر صفحه کلید منتقل می کنیم. را 100px در اینجا یک عدد دلخواه وجود دارد، نکته این است که چیزی را اضافه کنید که بزرگتر از ارتفاع ناو باشد.

در اینجا یک ویدیو در مورد نحوه کار آن وجود دارد:
نسخه ی نمایشی کدپن. همچنین می توانید تمام دموهای موجود در مجموعه Codepen را مشاهده کنید.
Outro
این همه برای این مقاله است. من چیزهای زیادی در مورد API صفحه کلید مجازی یاد گرفتم و بی صبرانه منتظر اجرای آن در پروژه بعدی خود هستم. آخرین چیزی که انتظار داشتم نوشتن 1600 کلمه در مورد چنین موضوعی بود. اگر این معنی دارد، به این معنی است که هرگز به دل خود در مورد چیزی که نمی دانید اعتماد نکنید. فقط شروع کنید و اتفاقات خوب در راه است.
افکار یا سوالی دارید؟ لطفاً برای من توییت کنید (با عرض پوزش X) @shadeed9 یا Mastodon یا Threads.
منابع
منابع زیر به من در تحقیقات اولیه در مورد موضوع کمک زیادی کرد.
ممنون که خواندید.


