مدتها «سرعت» و «دسترسپذیری» دو دغدغه جدا تلقی میشدند که توسط افراد متفاوتی پیگیری میشد. اما در سال ۲۰۲۶ این دو یک گفتگوی مشترک هستند. چیدمانی که با ۶۰ کیلوبایت CSS منتشر میشود اما رشته اصلی مرورگر را برای نیم ثانیه قفل میکند، برای کاربری که اهمیت دارد — کاربری که با یک گوشی ۹۰ دلاری در لبه شبکه است — سریع محسوب نمیشود.
این مقاله الگوهایی را معرفی میکند که تیم ما برای ساخت رابطهای فوری و سازگار با Screen Reader به کار میگیرد. از display: grid، Container Queryها و چند قطعه سرور برای کنار هم چیدن همهچیز استفاده خواهیم کرد.
با مدل محتوا شروع کنید
هر مسئله چیدمان در واقع یک مسئله محتوایی پنهان است. پیش از هر CSS، شکل دادهها را روی کاغذ بکشید — ترتیب ظاهر در مارکآپ، ترتیب نمایش بصری و ترتیب اعلان به کاربر. وقتی این سه با هم هماهنگ باشند، بقیه کار تقریباً فقط تایپوگرافی است.
سریعترین چیدمان آن است که مجبور نشدید دو بار آن را بکشید. یک بار در HTML تصمیم بگیرید و اجازه دهید CSS فقط مرتب کند — نه بازچینی. — بوترابی
یک گرید که با کانتینر خود تطبیق مییابد
Container Queryها بالاخره این امکان را دادهاند که کامپوننتها را بر اساس باکس میزبان اندازهگیری کنیم، نه viewport. نتیجه: یک کامپوننت کارت که در سایدبار، هیرو و گرید سهستونه بدون حتی یک Media Query کار میکند.
/* Container itself; the card responds. */
.card-wrap { container-type: inline-size; }
.card {
display: grid;
gap: 12px;
grid-template-columns: 1fr;
}
@container (min-width: 420px) {
.card { grid-template-columns: 160px 1fr; }
}
اتصال به یک بکاند واقعی
یک چیدمان قابلدسترس فقط به اندازه دادهای که نمایش میدهد خوب است. سرور باید یک شکل پایدار و معنادار از داده برگرداند — نه رشتههای HTML از قبل رندر شده و نه مجموعهای صاف از فیلدها که کلاینت مجبور باشد دوباره مونتاژ کند.
C# — یک Endpoint کمینه
این Endpoint گرید کارتهای سایت ما را تغذیه میکند. به نوع پاسخ توجه کنید: یک Record با Nullable صریح — فرانتاند هیچگاه مجبور به حدس زدن نیست که چه چیزی ممکن است گم شده باشد.
using Microsoft.AspNetCore.Mvc;
public record PostSummary(
string Slug,
string Title,
string? Excerpt,
DateOnly PublishedOn);
public static class BlogEndpoints
{
public static void MapBlog(this WebApplication app)
{
app.MapGet("/api/posts", async (IPostRepo repo) =>
{
var posts = await repo.RecentAsync(take: 12);
return Results.Ok(posts);
});
}
}
Python — تولید Sitemap
یک اسکریپت کوچک هر شب اجرا میشود تا Sitemap بهروز بماند. مهم خود اسکریپت نیست — مهم این است که یک سایت قابلدسترس باید قابلکشف هم باشد و قابلکشف بودن یک دغدغه زمان Build است.
from pathlib import Path
import httpx, datetime as dt
def build_sitemap(base: str) -> str:
posts = httpx.get(f"{base}/api/posts").json()
today = dt.date.today().isoformat()
urls = "\n".join(
f" <url><loc>{base}/posts/{p['slug']}</loc></url>"
for p in posts
)
return f"<?xml version='1.0'?>\n<urlset>\n{urls}\n</urlset>"
if __name__ == "__main__":
Path("sitemap.xml").write_text(build_sitemap("https://boutorabi.com"))
نکته: هر فایل Sitemap را زیر ۵۰٬۰۰۰ URL نگه دارید. اگر از این حد عبور کردید، بر اساس سال یا دسته آن را تقسیم کنید — هم موتورهای جستجو شما را تحسین میکنند و هم صورتحساب CDN.
SQL — ایندکسی که کوئری را ارزان میکند
این Endpoint فقط یک کوئری اجرا میکند. ارزان است چون جدول ایندکس مناسب دارد. اگر یک نکته از این بخش با خود ببرید: برای کوئریای که واقعاً اجرا میکنید ایندکس بسازید، نه برای کوئریای که شاید روزی نیاز شود.
-- Recently published posts, newest first.
CREATE INDEX ix_posts_published
ON posts (published_on DESC)
WHERE status = 'published';
SELECT slug, title, excerpt, published_on
FROM posts
WHERE status = 'published'
ORDER BY published_on DESC
LIMIT 12;
چه چیزهایی را اندازه بگیرید
پس از انتشار چیدمان، این موارد را به ترتیب اندازهگیری کنید:
- Largest Contentful Paint — زیر ۲٫۵ ثانیه روی یک گوشی اندروید میانرده.
- Cumulative Layout Shift — زیر ۰٫۱، حتی برای تبلیغات استثنا قائل نشوید.
- عمق اولین Tab با کیبورد — چند Tab تا رسیدن به محتوای اصلی؟ سه یا کمتر.
- نواحی Screen Reader — یک
<main>، یک<nav>و یک<footer>.
جمعبندی
هیچکدام از اینها عجیب و غریب نیستند. Container Queryها امروز همهجا هستند. Minimal APIها روتین شدهاند. ایندکسهای درست قدیمیترین ترفند دنیای دادهاند. برد واقعی از آنجا میآید که اینها را با هم، با قصد و نیت روشن و با کاربر روی گوشی کند در ذهن، انجام دهیم. توسعه وب در ۲۰۲۶ این شکلی است — و راستش، باید یک دهه پیش هم همین شکلی میبود.
اگر چیزی با این ایدهها ساختید، برایم بفرستید — همه را میخوانم.
دیدگاهها
۰ پاسخ