CSS3 والتصميم المتجاوب

الأشكال وshape-outside

20 دقيقة الدرس 46 من 60

مقدمة في أشكال CSS ولف النص

في تصميم الويب التقليدي، يلتف النص دائما حول صناديق مستطيلة. كل عنصر في الصفحة هو مستطيل، لذلك عندما تعوّم صورة، يتدفق النص المحيط في خطوط مستقيمة على طول الحدود المستطيلة للصورة. هذا ينشئ شعورا صلبا وصندوقيا لا يتطابق مع التخطيطات العضوية الموجودة في المجلات المطبوعة والصحف والتصاميم التحريرية حيث يتدفق النص بأناقة حول الصور الدائرية والرسوم التوضيحية المنحنية والأشكال غير المنتظمة.

أشكال CSS تغير كل ذلك. خاصية shape-outside تتيح لك تحديد شكل غير مستطيل يلتف حوله النص. بدلا من محاذاة الحواف المستقيمة لصندوق العنصر المعوّم، يمكن للنص أن يتدفق على طول الدوائر والأشكال البيضاوية والمضلعات وحتى محيطات الصور الشفافة. هذا يفتح لف نص بجودة تحريرية مباشرة في CSS، بدون حيل JavaScript أو التموضع اليدوي. عند دمجها مع clip-path (التي تعلمتها في الدرس السابق)، يمكنك إنشاء تخطيطات مذهلة بصريا حيث يتبع كل من الشكل المرئي ولف النص نفس المحيط.

كيف يعمل shape-outside

خاصية shape-outside تحدد شكلا يلتف حوله المحتوى السطري (النص). من المهم فهم متطلب حاسم: shape-outside يعمل فقط على العناصر المعوّمة. يجب أن يحتوي العنصر على float: left أو float: right لكي يأخذ الشكل مفعوله. هذا لأن shape-outside يعدل كيفية تفاعل منطقة التعويم مع المحتوى السطري المحيط -- وفقط العناصر المعوّمة تنشئ مناطق تعويم.

الشكل الذي تحدده مع shape-outside لا يغير مظهر العنصر بصريا. إنه يغير فقط الحدود غير المرئية التي يلتف حولها النص. لجعل الشكل المرئي للعنصر يتطابق مع شكل اللف، تقوم عادةً بدمج shape-outside مع clip-path باستخدام نفس قيم الشكل. فكر في shape-outside على أنه يتحكم في "حدود الاصطدام" للنص، بينما clip-path يتحكم في "الحدود المرئية" للعنصر.

صيغة shape-outside الأساسية

/* shape-outside يعمل فقط على العناصر المعوّمة */
.shaped-element {
    float: left;
    width: 200px;
    height: 200px;
    shape-outside: circle(50%);
}

/* بدون تعويم، shape-outside ليس له أي تأثير */
.not-floated {
    /* هذا لن يعمل -- العنصر غير معوّم */
    shape-outside: circle(50%);
}

/* شكل لف النص يمكن أن يكون: */
.example {
    float: left;

    /* دالة شكل أساسي */
    shape-outside: circle(50%);
    shape-outside: ellipse(40% 50%);
    shape-outside: polygon(0% 0%, 100% 0%, 50% 100%);
    shape-outside: inset(10px round 20px);

    /* صورة بقناة ألفا */
    shape-outside: url("shape-image.png");

    /* قيمة صندوق */
    shape-outside: margin-box;
    shape-outside: border-box;
    shape-outside: padding-box;
    shape-outside: content-box;

    /* إعادة تعيين */
    shape-outside: none;
}
تحذير: الخطأ الأكثر شيوعا مع shape-outside هو نسيان تعويم العنصر. إذا طبقت shape-outside على عنصر غير معوّم (بما في ذلك عناصر Flex أو عناصر Grid أو العناصر ذات التموضع المطلق)، سيتم تجاهله تماما. تأكد دائما من أن العنصر المستهدف يحتوي على float: left أو float: right.

الأشكال الأساسية مع shape-outside

توفر أشكال CSS نفس دوال الأشكال الأساسية الأربع المتاحة في clip-path: circle() وellipse() وpolygon() وinset(). عند استخدامها مع shape-outside، تحدد هذه المحيط الذي يلتف حوله النص.

circle()

دالة circle() تنشئ منطقة لف دائرية. يتدفق النص حول منحنى الدائرة بدلا من الحافة المستقيمة للصندوق المستطيل. هذه هي قيمة shape-outside الأكثر شيوعا وهي مثالية للصور الرمزية المستديرة والصور الدائرية والعناصر الزخرفية.

لف النص حول دائرة

/* صورة رمزية دائرية مع لف النص */
.avatar-float {
    float: left;
    width: 150px;
    height: 150px;
    border-radius: 50%;
    margin-right: 20px;
    margin-bottom: 10px;

    /* النص يلتف حول الدائرة بدلا من المستطيل */
    shape-outside: circle(50%);
}

/* دائرة مع موضع مخصص */
.offset-circle {
    float: right;
    width: 200px;
    height: 200px;
    shape-outside: circle(50% at 50% 50%);
    clip-path: circle(50%);
}

/* دائرة أصغر: النص يقترب من المركز */
.tight-circle {
    float: left;
    width: 180px;
    height: 180px;
    shape-outside: circle(40%);
    clip-path: circle(40%);
    /* نصف قطر 40% يعني أن النص يلتف أقرب من حافة العنصر */
}

/* دائرة أكبر: النص يبتعد أكثر */
.loose-circle {
    float: left;
    width: 180px;
    height: 180px;
    shape-outside: circle(60%);
    clip-path: circle(50%);
    /* شكل اللف 60% أكبر من الشكل المرئي 50% */
}
نصيحة: لاحظ كيف نستخدم كلا من shape-outside وclip-path معا. shape-outside يجعل النص يلتف حول شكل الدائرة، بينما clip-path يقطع العنصر بصريا لنفس الشكل. بدون clip-path، سيظل العنصر يبدو مستطيلا حتى لو كان النص يلتف بمنحنى. بدون shape-outside، سيبدو العنصر دائريا لكن النص سيظل يلتف حول المستطيل غير المرئي.

ellipse()

دالة ellipse() تنشئ منطقة لف بيضاوية. تقبل نصفي قطر -- أفقي وعمودي -- وموضعا اختياريا. هذا مفيد للعناصر العريضة أو الطويلة حيث لا تتناسب الدائرة الكاملة مع النسب.

لف النص حول شكل بيضاوي

/* صورة بيضاوية عريضة مع لف النص */
.oval-image {
    float: left;
    width: 250px;
    height: 180px;
    margin-right: 20px;
    shape-outside: ellipse(50% 50%);
    clip-path: ellipse(50% 50%);
}

/* شكل بيضاوي طويل وضيق */
.tall-ellipse {
    float: right;
    width: 150px;
    height: 300px;
    margin-left: 20px;
    shape-outside: ellipse(50% 50%);
    clip-path: ellipse(50% 50%);
}

/* شكل بيضاوي غير مركزي لتأثير فني */
.artistic-ellipse {
    float: left;
    width: 200px;
    height: 200px;
    shape-outside: ellipse(45% 50% at 60% 50%);
    clip-path: ellipse(45% 50% at 60% 50%);
}

polygon()

دالة polygon() تمنحك أكبر قدر من التحكم بتحديد شكل مخصص بأي عدد من الرؤوس. هذا يمكّن لف النص حول المثلثات والماسات والأسهم والأشكال غير المنتظمة وأي محيط يمكنك وصفه بحواف مستقيمة. كل رأس هو زوج إحداثيات باستخدام نسب مئوية أو أطوال.

لف النص حول مضلعات

/* مثلث: النص يلتف على طول الحواف القطرية */
.triangle-float {
    float: left;
    width: 200px;
    height: 200px;
    shape-outside: polygon(50% 0%, 100% 100%, 0% 100%);
    clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
}

/* شكل ماسي */
.diamond-float {
    float: right;
    width: 200px;
    height: 200px;
    margin-left: 15px;
    shape-outside: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
    clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
}

/* شكل زاويّ مخصص */
.angular-float {
    float: left;
    width: 250px;
    height: 300px;
    shape-outside: polygon(0% 0%, 100% 0%, 100% 70%, 60% 100%, 0% 100%);
    clip-path: polygon(0% 0%, 100% 0%, 100% 70%, 60% 100%, 0% 100%);
}

/* حافة مائلة -- شائعة في التصميم التحريري */
.slanted-float {
    float: left;
    width: 300px;
    height: 400px;
    shape-outside: polygon(0% 0%, 100% 0%, 70% 100%, 0% 100%);
    clip-path: polygon(0% 0%, 100% 0%, 70% 100%, 0% 100%);
}

/* شكل سهم يشير نحو النص */
.arrow-float {
    float: left;
    width: 200px;
    height: 150px;
    shape-outside: polygon(
        0% 0%, 75% 0%, 100% 50%, 75% 100%, 0% 100%
    );
    clip-path: polygon(
        0% 0%, 75% 0%, 100% 50%, 75% 100%, 0% 100%
    );
}

inset()

دالة inset() تنشئ شكلا مستطيلا مُزاحا من حواف العنصر، اختياريا مع زوايا مستديرة. بينما قد يبدو هذا زائدا (العنصر مستطيل بالفعل)، فإن inset() مفيدة لإنشاء مناطق لف مستديرة لا تتبع زوايا العنصر الحادة، أو لإنشاء مسافة بين الشكل وحافة العنصر.

لف النص مع inset()

/* لف مستطيل مستدير */
.rounded-float {
    float: left;
    width: 200px;
    height: 200px;
    margin-right: 20px;
    shape-outside: inset(0 round 30px);
    clip-path: inset(0 round 30px);
}

/* إزاحة مع مسافة -- النص يلتف أبعد عن العنصر */
.padded-float {
    float: right;
    width: 180px;
    height: 180px;
    shape-outside: inset(10px round 20px);
    clip-path: inset(10px round 20px);
}

/* لف على شكل كبسولة */
.pill-float {
    float: left;
    width: 250px;
    height: 100px;
    shape-outside: inset(0 round 50px);
    clip-path: inset(0 round 50px);
}

shape-outside مع الصور

واحدة من أقوى ميزات shape-outside هي القدرة على استخدام قناة ألفا للصورة لتحديد شكل اللف. بدلا من حساب إحداثيات المضلع يدويا، تقدم صورة ويقوم المتصفح تلقائيا بتتبع المناطق غير الشفافة لإنشاء حدود اللف. هذا مثالي لصور الأشخاص والمنتجات والرسوم التوضيحية وأي صورة بخلفية شفافة.

لف شكل قائم على الصور

/* النص يلتف حول المحيط الفعلي لصورة PNG */
.product-float {
    float: left;
    width: 300px;
    height: auto;
    margin-right: 20px;

    /* المتصفح يتتبع البكسلات غير الشفافة */
    shape-outside: url("product-cutout.png");

    /* العتبة: ما مدى شفافية البكسل ليُعتبر "خارج" الشكل */
    shape-image-threshold: 0.5;
}

/* صورة شخص بخلفية شفافة */
.person-float {
    float: right;
    width: 250px;
    margin-left: 20px;
    shape-outside: url("person-cutout.png");
    shape-image-threshold: 0.3;
}

/* استخدام نفس الصورة كمصدر وشكل */
<img class="shaped-img"
     src="irregular-shape.png"
     alt="الوصف" />

.shaped-img {
    float: left;
    width: 200px;
    shape-outside: url("irregular-shape.png");
    shape-image-threshold: 0.5;
    margin-right: 15px;
}
ملاحظة: عند استخدام صورة لـ shape-outside، يجب أن تكون الصورة مقدمة من نفس الأصل (نفس النطاق) أو مع رؤوس CORS المناسبة. الصور عبر الأصول بدون CORS ستُحظر بواسطة سياسة أمان المتصفح، وسيعود الشكل إلى الصندوق المستطيل للعنصر. إذا كانت صورك على CDN، تأكد من أن CDN يرسل رأس Access-Control-Allow-Origin.

shape-margin

خاصية shape-margin تضيف مسافة بين الشكل المحدد والنص الملتف. تعمل كمنطقة عازلة غير مرئية حول الشكل، تدفع النص بعيدا عن حافة الشكل. بدون shape-margin، قد يظهر النص قريبا جدا من حدود الشكل، مما يجعله صعب القراءة. تقبل هذه الخاصية قيمة طول (بكسل، em، rem) أو نسبة مئوية.

إضافة مساحة تنفس مع shape-margin

/* دائرة مع هامش -- النص يبتعد عن الحافة */
.avatar-with-margin {
    float: left;
    width: 150px;
    height: 150px;
    shape-outside: circle(50%);
    clip-path: circle(50%);

    /* فجوة 15 بكسل بين الدائرة والنص */
    shape-margin: 15px;
}

/* مضلع مع هامش كبير */
.triangle-with-margin {
    float: left;
    width: 200px;
    height: 200px;
    shape-outside: polygon(50% 0%, 100% 100%, 0% 100%);
    clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
    shape-margin: 20px;
}

/* شكل قائم على الصور مع هامش */
.product-with-margin {
    float: right;
    width: 250px;
    shape-outside: url("product.png");
    shape-image-threshold: 0.5;
    shape-margin: 25px;
    margin-left: 10px;
}

/* قيم هامش مختلفة لأحجام شاشات مختلفة */
.responsive-shape {
    float: left;
    width: 200px;
    height: 200px;
    shape-outside: circle(50%);
    clip-path: circle(50%);
    shape-margin: 10px;
}

@media (min-width: 768px) {
    .responsive-shape {
        shape-margin: 20px;
    }
}

@media (min-width: 1200px) {
    .responsive-shape {
        shape-margin: 30px;
    }
}
نصيحة: قيمة shape-margin محدودة بصندوق هامش العنصر. إذا كانت قيمة shape-margin ستدفع حدود اللف خارج صندوق هامش العنصر، يتم تقييدها إلى صندوق الهامش. هذا يعني أن قيم shape-margin الكبيرة جدا لن يكون لها تأثير إضافي يتجاوز حدود هامش العنصر الفعلي. اختبر دائما هوامش الشكل بصريا لضمان وجود مساحة تنفس كافية للنص دون إنشاء فجوات محرجة.

shape-image-threshold

خاصية shape-image-threshold تتحكم في عتبة قناة ألفا المستخدمة عند استخراج شكل من صورة. تحدد الحد الأدنى لمستوى العتامة الذي يجب أن يمتلكه البكسل ليُعتبر جزءا من الشكل. تقبل هذه الخاصية قيمة بين 0.0 (شفاف بالكامل) و1.0 (معتم بالكامل). البكسلات ذات قيمة ألفا أعلى من العتبة تكون داخل الشكل؛ البكسلات أدناها تكون خارجه.

التحكم في عتبة استخراج الشكل

/* عتبة منخفضة: حتى البكسلات المرئية قليلا تُعتبر جزءا من الشكل */
.sensitive-shape {
    float: left;
    width: 200px;
    shape-outside: url("soft-edge.png");
    shape-image-threshold: 0.1;
    /* يشمل البكسلات التي عتامتها 10% فقط */
}

/* عتبة افتراضية: البكسلات شبه الشفافة مشمولة */
.default-shape {
    float: left;
    width: 200px;
    shape-outside: url("cutout.png");
    shape-image-threshold: 0.5;
    /* يشمل البكسلات التي عتامتها 50% على الأقل */
}

/* عتبة عالية: فقط البكسلات شبه المعتمة تُحسب */
.strict-shape {
    float: left;
    width: 200px;
    shape-outside: url("fuzzy-edge.png");
    shape-image-threshold: 0.9;
    /* يشمل فقط البكسلات ذات عتامة 90%+ */
}

/* استخدام صورة تدرج كمصدر شكل */
.gradient-shape {
    float: left;
    width: 200px;
    height: 300px;
    /* يمكن استخدام التدرج كصورة لـ shape-outside */
    shape-outside: linear-gradient(to right, black 0%, transparent 100%);
    shape-image-threshold: 0.5;
    /* النص يلتف على طول خط العتامة 50% من التدرج */
}
ملاحظة: يمكن استخدام التدرجات اللونية مباشرة كقيم shape-outside، تماما كما يمكن استخدامها كقيم mask-image. عند استخدام تدرج، يحدد shape-image-threshold أين على طول التدرج تقع حدود اللف. عتبة 0.5 مع تدرج خطي من الأسود إلى الشفاف تنشئ حدود لف عند نقطة منتصف التدرج، مما ينتج تأثير لف نص قطري.

لف النص بأسلوب المجلات

حالة الاستخدام الأساسية لأشكال CSS هي إعادة إنشاء تخطيطات النص الأنيقة الموجودة في المجلات والصحف المطبوعة. في التصميم التحريري، يتدفق النص عادةً حول صور الأشخاص ولقطات المنتجات أو العناصر الزخرفية بأنماط عضوية غير مستطيلة. دعنا نبني عدة تخطيطات بأسلوب المجلات باستخدام shape-outside.

تخطيط مجلة: سيرة المؤلف مع صورة دائرية

<!-- هيكل HTML -->
<article class="author-bio">
    <img class="author-photo"
         src="author.jpg"
         alt="اسم المؤلف" />
    <h3>عن المؤلف</h3>
    <p>نص سيرة ذاتية طويل يلتف حول
       صورة المؤلف الدائرية مما ينشئ تخطيطا
       تحريريا أنيقا...</p>
</article>

<style>
.author-bio {
    max-width: 600px;
    line-height: 1.8;
    font-size: 1.1rem;
}

.author-photo {
    float: left;
    width: 180px;
    height: 180px;
    object-fit: cover;
    border-radius: 50%;
    margin-right: 10px;
    margin-bottom: 10px;

    shape-outside: circle(50%);
    shape-margin: 15px;
}
</style>

تخطيط مجلة: حرف استهلالي بشكل مخصص

/* حرف أول كبير زخرفي مع لف مشكّل */
.article-body::first-letter {
    /* ملاحظة: shape-outside لا يعمل على ::first-letter */
    /* نستخدم تقنية مختلفة للأحرف الاستهلالية */
}

/* بدلا من ذلك، نستخدم span معوّم للحرف الاستهلالي */
.drop-cap {
    float: left;
    font-size: 5rem;
    line-height: 0.8;
    padding-right: 10px;
    padding-top: 5px;
    font-family: Georgia, serif;
    color: #2c3e50;

    /* الشكل يسمح للنص بمحاذاة شكل الحرف */
    shape-outside: polygon(
        0% 0%, 100% 0%, 100% 100%, 60% 100%, 60% 60%, 0% 60%
    );
    shape-margin: 5px;
}

/* اقتباس بارز بشكل ماسي */
.pull-quote {
    float: right;
    width: 200px;
    height: 200px;
    margin: 0 0 20px 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    font-style: italic;
    font-size: 1.1rem;
    padding: 30px;
    background: #f0f4f8;

    shape-outside: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
    clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
    shape-margin: 15px;
}

تخطيط مجلة: صفحة تحريرية كاملة

/* صورة مميزة كبيرة معوّمة مع لف شكل مخصص */
.feature-image {
    float: left;
    width: 45%;
    max-width: 400px;
    margin: 0 30px 20px 0;

    /* الحافة المائلة تنشئ تدفق نص ديناميكي */
    shape-outside: polygon(0% 0%, 100% 0%, 80% 100%, 0% 100%);
    clip-path: polygon(0% 0%, 100% 0%, 80% 100%, 0% 100%);
    shape-margin: 20px;
}

.feature-image img {
    width: 100%;
    height: auto;
    display: block;
}

/* عنصر جانبي دائري */
.sidebar-callout {
    float: right;
    width: 180px;
    height: 180px;
    margin: 10px 0 20px 25px;
    background: linear-gradient(135deg, #667eea, #764ba2);
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    font-weight: bold;
    padding: 20px;

    shape-outside: circle(50%);
    clip-path: circle(50%);
    shape-margin: 18px;
}

/* تنسيق نص المقال */
.article-text {
    font-size: 1.05rem;
    line-height: 1.9;
    color: #333;
    text-align: justify;
    hyphens: auto;
}

دمج shape-outside مع clip-path

كما رأينا في الأمثلة أعلاه، shape-outside وclip-path هما رفيقان طبيعيان. shape-outside يتحكم في أين يلتف النص، وclip-path يتحكم في أي جزء من العنصر مرئي. باستخدام نفس قيم الشكل لكلتا الخاصيتين، تنشئ تأثيرا سلسا حيث يكون شكل العنصر المرئي وحدود لف النص متوافقين تماما.

shape-outside وclip-path متزامنان

/* نفس الشكل للف والرؤية */
.shaped-element {
    float: left;
    width: 250px;
    height: 250px;
    margin-right: 10px;

    /* كلاهما يستخدم نفس المضلع بالضبط */
    shape-outside: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
    clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
    shape-margin: 15px;
}

/* صورة سداسية */
.hex-image {
    float: left;
    width: 200px;
    height: 230px;
    object-fit: cover;
    margin-right: 10px;

    shape-outside: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
    clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
    shape-margin: 12px;
}

/* يمكنك استخدام أشكال مختلفة للف مقابل الرؤية */
.creative-shape {
    float: right;
    width: 200px;
    height: 200px;
    margin-left: 15px;

    /* منطقة لف أكبر من المنطقة المرئية */
    shape-outside: circle(55%);  /* النص يلتف أوسع */
    clip-path: circle(45%);      /* العنصر يظهر أصغر */
    shape-margin: 10px;
    /* ينشئ مساحة تنفس إضافية بين الشكل والنص */
}

/* شكل قائم على الصورة مع clip-path للمطابقة البصرية */
.cutout-photo {
    float: left;
    width: 280px;
    margin-right: 15px;

    /* كلاهما يستخدم نفس الصورة للاتساق */
    shape-outside: url("person-cutout.png");
    clip-path: url(#personClipPath);  /* قائم على SVG لحواف ناعمة */
    shape-image-threshold: 0.5;
    shape-margin: 20px;
}
ملاحظة: يمكنك استخدام أشكال مختلفة عمدا لـ shape-outside وclip-path. على سبيل المثال، دائرة لـ clip-path مقترنة بدائرة أكبر قليلا لـ shape-outside تنشئ مسافة بصرية بين حافة العنصر والنص الملتف. هذه التقنية مفيدة عندما لا يمنحك shape-margin وحده تحكما كافيا في المسافات.

تخطيطات تحريرية إبداعية

دعنا ندفع حدود أشكال CSS لإنشاء تخطيطات تحريرية إبداعية حقا تفخر بها أي مصمم طباعة. هذه الأمثلة توضح تقنيات متقدمة تجمع بين أشكال معوّمة متعددة ومضلعات مخصصة ومحيطات قائمة على الصور.

لف النص من الجانبين

/* النص يلتف حول أشكال على كلا الجانبين */
.two-sided-layout {
    max-width: 800px;
    margin: 0 auto;
    line-height: 1.8;
}

.left-shape {
    float: left;
    width: 150px;
    height: 300px;
    shape-outside: polygon(0% 0%, 100% 10%, 80% 50%, 100% 90%, 0% 100%);
    clip-path: polygon(0% 0%, 100% 10%, 80% 50%, 100% 90%, 0% 100%);
    background: linear-gradient(180deg, #e74c3c, #c0392b);
    shape-margin: 15px;
}

.right-shape {
    float: right;
    width: 150px;
    height: 300px;
    shape-outside: polygon(100% 0%, 0% 10%, 20% 50%, 0% 90%, 100% 100%);
    clip-path: polygon(100% 0%, 0% 10%, 20% 50%, 0% 90%, 100% 100%);
    background: linear-gradient(180deg, #3498db, #2980b9);
    shape-margin: 15px;
}

/* النص يتدفق بين الشكلين مما ينشئ قناة ضيقة */

لف النص حول صورة منتج

/* عرض المنتج: النص يحاذي محيط المنتج */
.product-showcase {
    max-width: 700px;
    line-height: 1.8;
    font-size: 1.05rem;
}

.product-image {
    float: left;
    width: 350px;
    margin: 0 25px 15px 0;

    /* الشكل القائم على الصورة يتتبع الخطوط الخارجية للمنتج */
    shape-outside: url("headphones-cutout.png");
    shape-image-threshold: 0.4;
    shape-margin: 20px;
}

.product-image img {
    width: 100%;
    height: auto;
    /* clip-path غير مطلوب لأن PNG يحتوي بالفعل على شفافية */
}

/* بديل للمتصفحات بدون دعم الأشكال */
@supports not (shape-outside: url("test.png")) {
    .product-image {
        border-radius: 20px;
        margin-right: 30px;
    }
}

اعتبارات التصميم المتجاوب

تتطلب أشكال CSS اهتماما خاصا للتصميم المتجاوب. العناصر المعوّمة مع الأشكال يمكن أن تسبب مشاكل في التخطيط على الشاشات الصغيرة حيث لا توجد مساحة كافية للنص للتدفق حول الشكل. دائرة بعرض 200 بكسل على شاشة بعرض 320 بكسل تترك مساحة صغيرة جدا لنص مقروء. يجب أن تخطط لهذه السيناريوهات لضمان تدهور تخطيطاتك التحريرية بأناقة على الأجهزة المحمولة.

جعل تخطيطات الأشكال متجاوبة

/* الأنماط الأساسية: لا أشكال على المحمول */
.editorial-image {
    display: block;
    width: 100%;
    max-width: 400px;
    margin: 0 auto 20px;
    border-radius: 12px;
}

/* تمكين الأشكال فقط على الشاشات الواسعة بما يكفي لتدفق النص */
@media (min-width: 768px) {
    .editorial-image {
        float: left;
        width: 250px;
        margin: 0 25px 15px 0;
        border-radius: 0;
        shape-outside: circle(50%);
        clip-path: circle(50%);
        shape-margin: 15px;
    }
}

@media (min-width: 1024px) {
    .editorial-image {
        width: 300px;
        shape-margin: 25px;
    }
}

/* نهج آخر: تبسيط الشكل على الشاشات الأصغر */
.complex-shape {
    float: left;
    width: 200px;
    height: 200px;
}

@media (min-width: 768px) {
    .complex-shape {
        shape-outside: circle(50%);
        clip-path: circle(50%);
        shape-margin: 15px;
    }
}

@media (min-width: 1024px) {
    .complex-shape {
        /* شكل أكثر تعقيدا على الشاشات الأكبر */
        shape-outside: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
        clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
        shape-margin: 20px;
    }
}

/* إزالة التعويم عندما يصبح النص مزدحما جدا */
@media (max-width: 500px) {
    .shaped-float {
        float: none;
        shape-outside: none;
        clip-path: none;
        width: 100%;
        margin: 0 0 20px 0;
    }
}
تحذير: اختبر دائما تخطيطات الأشكال على منافذ العرض الضيقة. إذا كان الشكل المعوّم يأخذ أكثر من حوالي 50% من عرض الحاوية، يصبح عمود النص المتبقي ضيقا جدا للقراءة المريحة (خاصة مع النص المضبوط). قاعدة عامة جيدة هي تعطيل shape-outside وfloat على الشاشات حيث سيكون عمود النص أقل من 200 بكسل عرضا.

دعم المتصفحات

أشكال CSS (shape-outside وshape-margin وshape-image-threshold) لها دعم جيد في جميع المتصفحات الحديثة. Chrome وEdge وSafari وOpera وFirefox جميعها تدعم المواصفات الكاملة. Internet Explorer لا يدعم أشكال CSS على الإطلاق، لكنه في الأساس منتهي. الاعتبار الرئيسي هو أن الأشكال هي تحسين تدريجي -- عندما لا تكون مدعومة، يلتف النص ببساطة حول الصندوق المستطيل كالمعتاد، لذلك يظل المحتوى قابلا للوصول والقراءة بالكامل.

التحسين التدريجي مع استعلامات الميزات

/* الأنماط الأساسية: تعمل في كل مكان */
.author-image {
    float: left;
    width: 180px;
    height: 180px;
    border-radius: 50%;
    margin-right: 20px;
    margin-bottom: 10px;
    object-fit: cover;
}

/* أنماط محسنة: فقط عند دعم الأشكال */
@supports (shape-outside: circle(50%)) {
    .author-image {
        shape-outside: circle(50%);
        shape-margin: 15px;
        margin-right: 5px;
        /* تقليل الهامش لأن shape-margin يتولى المسافات */
    }
}

/* كشف كامل للميزات مع أشكال الصور */
@supports (shape-outside: url("test.png")) {
    .product-photo {
        shape-outside: url("product.png");
        shape-image-threshold: 0.5;
        shape-margin: 20px;
    }
}

/* بديل للمتصفحات القديمة جدا: بدون تعويم على الإطلاق */
@supports not (shape-outside: circle(50%)) {
    .shaped-element {
        /* اختياريا إزالة التعويم تماما لتخطيط أبسط */
        float: none;
        display: block;
        margin: 0 auto 20px;
        width: 100%;
        max-width: 300px;
    }
}

أمثلة عملية

دعنا نبني أمثلة كاملة جاهزة للإنتاج توضح أشكال CSS في سيناريوهات واقعية. كل مثال يتضمن هيكل HTML الكامل وCSS اللازم لإعادة إنشاء التخطيط.

منشور مدونة مع صورة المؤلف

<!-- HTML -->
<article class="blog-post">
    <h1>فهم تخطيطات CSS الحديثة</h1>
    <div class="post-meta">
        <img class="author-avatar"
             src="author-avatar.jpg"
             alt="سارة أحمد" />
        <div class="post-content">
            <p>تطورت CSS بشكل كبير خلال العقد الماضي.
               من الأيام الأولى للتخطيطات القائمة على الجداول
               إلى العصر الحديث لـ Grid وFlexbox، تم تحويل
               طريقة بناء صفحات الويب بالكامل...</p>
            <p>يضيف إدخال أشكال CSS بعدا آخر
               لقدرات التخطيط لدينا، مما يسمح للنص
               بالتدفق حول أشكال غير مستطيلة لأول
               مرة في تاريخ CSS...</p>
        </div>
    </div>
</article>

<style>
.blog-post {
    max-width: 680px;
    margin: 0 auto;
    padding: 40px 20px;
    font-family: Georgia, serif;
    line-height: 1.8;
    color: #2c3e50;
}

.blog-post h1 {
    font-size: 2rem;
    margin-bottom: 30px;
}

.author-avatar {
    float: left;
    width: 120px;
    height: 120px;
    object-fit: cover;
    border-radius: 50%;
    margin-right: 5px;
    margin-bottom: 10px;
}

@supports (shape-outside: circle(50%)) {
    .author-avatar {
        shape-outside: circle(50%);
        shape-margin: 15px;
    }
}
</style>

صفحة هبوط منتج مع لف الشكل

<!-- HTML -->
<section class="product-section">
    <img class="product-hero"
         src="smartphone-cutout.png"
         alt="طراز الهاتف الذكي الجديد" />
    <h2>مستقبل الأجهزة المحمولة</h2>
    <p>يتميز أحدث هاتفنا الذكي بشاشة ثورية
       من الحافة إلى الحافة، وقدرات ذكاء اصطناعي
       متقدمة، وأقوى نظام كاميرا أنشأناه على
       الإطلاق. بتصميم أنيق يتناسب تماما مع
       يدك، يعيد تعريف ما يمكن أن يكون عليه
       الجهاز المحمول...</p>
    <p>العدسة فائقة العرض تلتقط مناظر طبيعية
       خلابة، بينما عدسة الماكرو تكشف تفاصيل
       غير مرئية بالعين المجردة. مع محرك معالجة
       الصور العصبي، كل صورة هي تحفة فنية...</p>
</section>

<style>
.product-section {
    max-width: 750px;
    margin: 0 auto;
    padding: 40px 20px;
    line-height: 1.8;
    font-size: 1.1rem;
}

.product-hero {
    width: 100%;
    max-width: 300px;
    display: block;
    margin: 0 auto 20px;
}

@media (min-width: 768px) {
    .product-hero {
        float: right;
        width: 280px;
        margin: 0 0 20px 30px;
        shape-outside: url("smartphone-cutout.png");
        shape-image-threshold: 0.4;
        shape-margin: 25px;
    }
}
</style>

كتلة اقتباس مع شكل زخرفي

/* اقتباس زخرفي بشكل زاويّ */
.quote-block {
    position: relative;
    max-width: 700px;
    margin: 40px auto;
    padding: 0 20px;
    line-height: 1.8;
}

.quote-decoration {
    float: left;
    width: 80px;
    height: 80px;
    background: linear-gradient(135deg, #f39c12, #e67e22);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 3rem;
    color: white;
    font-family: Georgia, serif;
    margin-right: 5px;
    margin-bottom: 5px;

    shape-outside: polygon(0% 0%, 100% 0%, 100% 100%);
    clip-path: polygon(0% 0%, 100% 0%, 100% 100%);
    shape-margin: 10px;
}

.quote-text {
    font-size: 1.2rem;
    font-style: italic;
    color: #555;
}

.quote-attribution {
    display: block;
    margin-top: 15px;
    font-style: normal;
    font-weight: bold;
    color: #333;
}

تغيير شكل تفاعلي عند النقر

/* ملاحظة: shape-outside لا يدعم الانتقالات/الحركات */
/* لكن يمكننا تبديل الأشكال باستخدام فئات مع JavaScript */

.morphable-float {
    float: left;
    width: 200px;
    height: 200px;
    margin-right: 10px;
    background: url("photo.jpg") center/cover;
    transition: clip-path 0.4s ease;

    /* الافتراضي: دائرة */
    shape-outside: circle(50%);
    clip-path: circle(50%);
    shape-margin: 15px;
}

/* JavaScript يبدّل هذه الفئة */
.morphable-float.hexagon {
    shape-outside: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
    clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
}

/* سكريبت لتبديل الشكل */
<script>
const el = document.querySelector('.morphable-float');
el.addEventListener('click', () => {
    el.classList.toggle('hexagon');
    /* ملاحظة: إعادة تدفق النص تحدث فورا؛
       فقط clip-path يتحرك بصريا */
});
</script>
ملاحظة: على عكس clip-path، لا يمكن تحريك أو انتقال خاصية shape-outside بـ CSS. تغيير قيمة shape-outside يتسبب في إعادة تدفق النص فورا بدون أي انتقال سلس. إذا كنت بحاجة لتغييرات شكل متحركة مع لف النص، يجب استخدام JavaScript لتبديل الفئات، وستكون إعادة تدفق النص فورية بينما يمكن لتغيير clip-path البصري أن يتحرك بسلاسة.

التمرين 1: مقال مجلة مع لف الصور

أنشئ تخطيط مقال بأسلوب المجلات. ابدأ بصورة بطل كبيرة في الأعلى تمتد بالعرض الكامل. تحتها، عوّم صورة مؤلف دائرية إلى اليسار باستخدام shape-outside: circle(50%) مع shape-margin: 20px وclip-path متطابق. يجب أن تلتف الفقرتان الأوليان من النص حول الدائرة. ثم أضف اقتباسا بارزا مستطيلا معوّما إلى اليمين مع shape-outside ماسي باستخدام polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%). يجب أن يحتوي الاقتباس البارز على لون خلفية ونص مائل في المركز. أسفل المقال، عوّم صورة منتج (بخلفية PNG شفافة) إلى اليسار، باستخدام shape-outside: url() مع shape-image-threshold: 0.5 بحيث يلتف النص بإحكام حول محيط المنتج الفعلي. أضف shape-margin: 25px لمساحة التنفس. اجعل التخطيط متجاوبا: على الشاشات الأضيق من 768 بكسل، أزل جميع التعويمات والأشكال بحيث تتراص الصور عموديا فوق النص. استخدم @supports (shape-outside: circle(50%)) للتحسين التدريجي.

التمرين 2: عرض محفظة أعمال إبداعي

ابنِ قسم عرض محفظة أعمال مع ثلاثة مدخلات مشاريع. كل مدخل يحتوي على صورة مشروع معوّمة بالتناوب يسارا ويمينا (الأول يسارا، الثاني يمينا، الثالث يسارا). للمدخل الأول، استخدم shape-outside: polygon() مع حافة مائلة (مثلا polygon(0% 0%, 100% 0%, 85% 100%, 0% 100%)) بحيث يتدفق النص على طول القطر. للمدخل الثاني (معوّم لليمين)، استخدم shape-outside: circle(50%) للف نص دائري. للمدخل الثالث، استخدم shape-outside: ellipse(50% 40%) للف بيضاوي. كل صورة معوّمة يجب أن تحتوي على clip-path مطابق وshape-margin بقيمة 20 بكسل. أضف clearfix بين المدخلات بحيث يبدأ كل منها على سطر جديد. استخدم CSS Grid أو تخطيط كتل بسيط للهيكل العام. على الشاشات الأقل من 600 بكسل عرضا، أزل جميع الأشكال والتعويمات، واعرض كل مشروع كبطاقة مكدسة مع الصورة فوق الوصف. أضف استعلامات @supports للتدهور الأنيق لأي متصفح لا يدعم shape-outside.