UIDex

الصورة الرمزية ومجموعتها

Avatar and Avatar Group

<img alt> / AvatarGroup

اسمه كمانأفاتار، الصورة الشخصية، صورة المستخدم، بديل الحروف الأولى، صفّ الصور المتداخلة، أيقونة الحساب، profile picture، user avatar، initials avatar، avatar stack، facepile، profile photo

الصورة الرمزية هي الرسم الصغير الذي يدلّ على كيان واحد له اسم: شخص أو فريق أو شركة. تعرض صورة إن وُجدت، فإن غابت أو فشل تحميلها ظهر مكانها بديل نصّي من الحروف الأولى للاسم فوق خلفية ملوّنة. وشكلها إشارة يقرأها المستخدم قبل أي نصّ: الدائرة للأشخاص والمربّع المستدير للمؤسسات، والخلط بينهما داخل قائمة واحدة يضيّع الإشارة كلها. وهي ليست أيقونة، لأن الأيقونة تدلّ على فعل أو نوع (حذف، مجلّد، إعدادات) ورسمها واحد يتكرّر في كل مكان، أمّا الصورة الرمزية فتدلّ على كيان بعينه ولا تصحّ لغيره. وليست شارة (badge)، فالشارة رقم أو حالة تُلصق على عنصر آخر لتصفه، بينما الصورة الرمزية هي العنصر نفسه لا الزخرفة التي عليه. وليست شريحة (chip)، فالشريحة تكتب الاسم بالحروف، ولها غالباً زرّ إزالة، وتعيش داخل حقل إدخال. أمّا مجموعة الصور الرمزية فصفّ متداخل يجيب بلمحة عن سؤال «من يعمل على هذا؟»، وهي اختصار لقائمة لا بديل عنها، فإن كان المستخدم يحتاج الأسماء فضع قائمة كاملة خلف العدّاد.

لو قلت عليه…

«الدايرة اللي فيها صورة اليوزر»«الحرف اللي بيظهر لما ميكونش في صورة»«الصور الصغيّرة المركّبة فوق بعضها في صفّ»«النقطة الخضرا اللي على صورة الشخص»«الدايرة اللي مكتوب فيها زائد تلاتة»

العيّنة الحيّة

تفاعل مع الديمو. كل الأجزاء حقيقية ومرقّمة.

يعملون على «خطة الربع الرابع»

سينر
طارق مسعودمحرّر، متاح الآن
RTLأول صورة عند اليمين، وكل تالية تنزلق تحتها، والعدّاد في نهاية الصفّ

تشريح العنصر: كل جزء واسمه

مرّر على أي سطر ليتحدّد مكانه في الديمو فوق.

برومبت البناء

ابنِ مكوّن صورة رمزية ومجموعة صور رمزية. اجعل الصورة عنصر <img> حقيقياً بـ object-fit: cover ونصّ بديل يحمل اسم صاحبها، واترك alt="" فقط حين يكون الاسم مكتوباً بجانبها. اربط onError بتبديل الصورة إلى بديل الحروف الأولى حتى لا يرسم المتصفّح أيقونة الصورة المكسورة، واشتقّ الحروف من الاسم الكامل لا من البريد، وافصل بين الحرفين العربيين بـ U+200C حتى لا يتّصلا في شكل واحد. استعمل الدائرة للأشخاص والمربّع المستدير للمؤسسات. أضف نقطة حالة اختيارية مثبّتة بـ inset-inline-end: 0 و inset-block-end: 0 مع حلقة بلون الخلفية، وضع الحالة في نصّ مرئي أو اسم مقروء لا في اللون وحده. في المجموعة اعرض من ثلاث إلى خمس صور، ونفّذ التداخل بـ margin-inline-start سالب على كل صورة بعد الأولى، وأعطِ كل صورة z-index يسير عكس ترتيب DOM لترتفع الأولى فوق الجميع، ولا تعكس هذه القيم داخل [dir="rtl"] ولا تستعمل flex-direction: row-reverse. واجعل ما زاد شارة «‎+N‎» عند نهاية الصفّ، زرّاً حقيقياً يفتح القائمة الكاملة، باسم مقروء يقول كم بقي، مع عزل الرمز في span بـ dir="ltr" حتى لا ينقلب في السياق العربي. واستعمل الخصائص المنطقية في كل مكان: margin-inline و inset-inline و padding-inline، ولا تكتب left أو right أو margin-left. وأخيراً لا تُدخل الصور ولا الشعارات في أي قاعدة قلب عامة عند الانعكاس.

سلوكه في الاتجاه من اليمين لليسار

الجزء ده حصري عندنا.

اتجاه التداخل

ينعكس

في الإنجليزية تجلس أول صورة عند اليسار وتنزلق كل تالية تحت سابقتها نحو اليمين، وفي العربية ينقلب هذا كلّه: أول صورة عند اليمين والصفّ ينمو نحو اليسار. اكتب الإزاحة margin-inline-start: -8px على كل صورة عدا الأولى، فهي تسحب الصورة نحو سابقتها أياً كانت جهة «السابقة». أمّا margin-left: -8px فيظلّ يسحب نحو اليسار بعد الانعكاس، فتنزلق كل صورة تحت التي تليها بدل التي تسبقها، وتلتصق الأولى بالثانية بلا تداخل، وتسحب الأخيرة حافّة الصفّ البعيدة ثمانية بكسل إلى الداخل. ولا تعالجها بإضافة margin-right داخل [dir="rtl"]، فالخاصّية المنطقية تؤدّي العمل كاملاً بلا استثناء.

ترتيب التراكب

لا ينعكس

المظهر الذي تنزلق فيه كل صورة تحت سابقتها يأتي من z-index يسير عكس ترتيب DOM: الأولى تأخذ أعلى قيمة والأخيرة أدناها، لأن المتصفّح بغير ذلك يرسم العنصر المتأخّر فوق المتقدّم فينقلب المظهر. وهذه القيم لا تتغيّر بتغيّر الاتجاه، فـ z-index خاصّية رسم لا خاصّية تخطيط وليس لها صيغة منطقية أصلاً، وإعادة عكسها داخل [dir="rtl"] ترفع آخر صورة فوق الجميع ويظهر الصفّ مقلوباً. والذي ينتقل فعلاً هو الهلال المخفيّ من كل دائرة: يبقى عند البداية المنطقية، فينتقل من الحافّة اليسرى لكل صورة في الإنجليزية إلى حافّتها اليمنى في العربية. وتجنّب حيلة flex-direction: row-reverse مع ترتيب DOM معكوس للوصول إلى نفس المظهر، لأن row-reverse تُحسب بالنسبة إلى direction فتقلب الصفّ العربي كلّه رأساً على عقب.

ركن نقطة الحالة

ينعكس

النقطة تجلس في الزاوية السفلية عند النهاية المنطقية: أسفل اليمين في الإنجليزية وأسفل اليسار في العربية. ثبّتها بـ inset-inline-end: 0 مع inset-block-end: 0 بدل right: 0. والفخّ في الإزاحة الصغيرة التي تدفعها نحو الحافّة، فـ transform ليس له صيغة منطقية أصلاً: القيمة الموجبة في translate(25%, 25%) تدفع نحو اليمين دائماً، فحين تنتقل نقطة الارتساء إلى الجهة اليسرى في العربية صارت الإزاحة نفسها تزحف بالنقطة إلى داخل الوجه بدل أن تخرج بها. اضرب المحور الأفقي في إشارة ‎--dir‎ قيمتها ‎-1‎ داخل [dir="rtl"]، أو استغنِ عن transform واستعمل inset-inline-end: -2px. وإن وضع مكوّن جاهز الشارة بقيمة اسمها "left" أو "right" فالاسم فيزيائي: MUI يحلّ anchorOrigin بالنسبة إلى theme.direction، فتحقّق هل تفعل مكتبتك المثل قبل أن تعتمد على انعكاسها وحدها.

موضع العدّاد وعلامة الزائد

ينعكس

العدّاد يقف عند النهاية المنطقية للصفّ، فينتقل من أقصى اليمين في الإنجليزية إلى أقصى اليسار في العربية. وهذا يحدث وحده إن كان الصفّ flex عادياً وكانت الشارة آخر عنصر في DOM، أمّا لو رصفت الصور بـ position: absolute مع left: calc(i * 20px) فانقل الحساب إلى inset-inline-start وإلا استقرّ العدّاد فوق أول صورة. ويبقى النصّ نفسه محتاجاً إلى علاج مستقلّ عن التخطيط. فعلامة الزائد لا اتجاه لها: صنف U+002B في خوارزمية Unicode للاتجاه الثنائي هو ES، وهو صنف ضعيف لا قويّ ولا محايد، فتأخذ العلامة اتجاه ما حولها ويُرسم ما كُتب «+٣» على السطر العربي هكذا «٣+». هذا سلوك سليم من الخوارزمية وهو مع ذلك ليس ما رسمه المصمّم، فاعزل الرمز في span بـ dir="ltr"، وهي سمة تمنحه unicode-bidi: isolate من ورقة أنماط المتصفّح نفسها، أو اكتب العدد لفظاً مثل «و٣ آخرون».

ما لا ينعكس: الصورة والحروف

لا ينعكس

الصورة محتوى لا زخرفة. والقاعدة الشاملة ‎[dir="rtl"] img, [dir="rtl"] svg { transform: scaleX(-1) }‎ التي يكتبها البعض لقلب الأيقونات تقلب معها الوجوه والشعارات وأي حروف مرسومة داخل الشعار، فاقصر القلب على صنف تضعه على الأسهم وحدها. وخاصّية object-position تقبل الكلمات الفيزيائية فقط، وهذا هو الصواب هنا لأن القصّ يخصّ الصورة لا الصفحة: قيمة object-position: right center تظلّ تعني الحافّة اليمنى للملفّ بعد الانعكاس، وهو المطلوب. أمّا الحروف الأولى فنصّ يرتّبه محرّك الاتجاه الثنائي وحده، فلا تعكس ترتيبه يدوياً في العربية، ووسّطه بـ text-align: center حتى لا يختلف موضع الحرف الواحد عن موضع الحرفين.

أسماؤه في الكود

كل سطر هو كلمة مكتبة واحدة عن نفس الشيء. خد السطر اللي بيكلّم مشروعك.

HTML<img alt="…" onerror>الـ alt يحمل الاسم، و onerror هو ما يضع الحروف الأولى مكان أيقونة الصورة المكسورة.
ARIArole="img" + aria-labelالصورة الرمزية المبنيّة من <div> وحروف ليست صورة في شجرة الوصول حتى تُعلن هكذا، و role="img" يحجب الحروف بداخله فيصير aria-label هو حامل الاسم كلّه.
Radix UI<Avatar.Image> + <Avatar.Fallback delayMs>البديل ينتظر delayMs قبل أن يُرسم، فلا تومض الحروف الأولى على اتصال سريع.
shadcn/ui<AvatarImage> + <AvatarFallback>البديل عنصر شقيق لا خاصّية، فتركه فارغاً يعطيك دائرة خالية عند فشل الصورة.
Material UI<AvatarGroup max={4}>الرقم يشمل شارة الفائض نفسها، فـ max={4} يعرض ثلاثة وجوه و«+N».
Ant Design<Avatar.Group maxCount={3}>هنا الرقم يعدّ الوجوه فقط، فنفس القيمة تعطيك دائرة أكثر ممّا يعطيه ماتيريال.
CSSmargin-inline-start: -0.5remالهامش المنطقي السالب هو ما يجعل التداخل يتبع اتجاه الصفحة بلا استثناء لـ RTL.

شوف كمان

آخر تحديث · 2026-08-19