طباعة مستجيبة للسوائل مع CSS Poly Fluid Sizing
نشرت: 2022-03-10في هذه المقالة ، سوف ننتقل إلى مستوى آخر. سنقوم بفحص كيفية إنشاء طباعة مرنة وقابلة للتطوير عبر نقاط توقف متعددة وأحجام خطوط محددة مسبقًا باستخدام ميزات المتصفح المدعومة جيدًا وبعض الجبر الأساسي. أفضل جزء هو أنه يمكنك أتمتة كل شيء باستخدام Sass.
مزيد من القراءة على SmashingMag:
- طباعة السوائل حقًا بوحدتي vh و vw
- الأنماط المطبعية في تصميم النشرة الإخبارية بالبريد الإلكتروني بتنسيق HTML
- الأمثلة الجيدة والسيئة والعظيمة لطباعة الويب
- أدوات وموارد لطباعة ويب أكثر فائدة
عند العمل مع مصممين مبدعين على تصميمات صفحات الويب ، من الشائع إلى حدٍ ما تلقي لوحات / تخطيطات متعددة من Sketch أو Photoshop ، واحدة لكل نقطة توقف. في هذا التصميم ، ستكون العناصر (مثل عنوان h1
) عادةً بأحجام مختلفة في كل نقطة توقف. علي سبيل المثال:
- يمكن أن يكون
h1
في التخطيط الصغير22px
- يمكن أن يكون
h1
في التخطيط المتوسط24px
- يمكن أن يكون
h1
في التخطيط الكبير34px
يستخدم الحد الأدنى من CSS لهذا الغرض استعلامات الوسائط:
h1 { font-size: 22px; } @media (min-width:576px) { h1 { font-size: 22px; } } @media (min-width:768px) { h1 { font-size: 24px; } } @media (min-width:992px) { h1 { font-size: 34px; } }
هذه خطوة أولى جيدة ، لكنك تقصر font-size
على ما حدده المصمم فقط في نقاط التوقف المتوفرة. ماذا سيقول المصمم إذا سألت ، "ماذا يجب أن يكون font-size
في إطار عرض بعرض 850 بكسل؟" الجواب في معظم الحالات هو أنه سيكون في مكان ما بين 24 بكسل و 34 بكسل. لكن في الوقت الحالي ، يبلغ حجمها 24 بكسل فقط وفقًا لـ CSS الخاص بك ، وهو على الأرجح ليس ما كان يتصوره المصمم.
خيارك في هذه المرحلة هو حساب الحجم الذي يجب أن يكون عليه وإضافة نقطة توقف أخرى. هذا سهل بما فيه الكفاية. لكن ماذا عن جميع القرارات الأخرى؟ ما هو font-size
يجب أن يكون بعرض 800 بكسل؟ ماذا عن 900 بكسل؟ ماذا عن 935 بكسل؟ من الواضح أن المصمم لن يزودك بتخطيط كامل لكل دقة ممكنة. حتى لو فعلوا ذلك ، هل يجب أن تضيف العشرات (أو المئات) من نقاط التوقف لجميع font-sizes
المختلفة التي يطلبها المصمم؟ بالطبع لا.
يتم تغيير حجم التنسيق بالفعل بسلاسة مع عرض إطار العرض الخاص بك. ألن يكون لطيفًا إذا تم تحجيم أسلوبك بشكل متوقع مع تخطيطك المرن؟ ماذا يمكننا أن نفعل لتحسين هذا؟
وحدات منفذ العرض للإنقاذ؟
وحدات منفذ العرض هي خطوة أخرى في الاتجاه الصحيح. إنها تسمح للنص بتغيير حجمه بسلاسة مع تخطيطاتك. ودعم المتصفح رائع هذه الأيام.
لكن جدوى وحدات Viewport تعتمد بشكل كبير على التصميمات الإبداعية الأصلية لصفحة الويب. سيكون من الرائع تعيين font-size
الخاص بك باستخدام vw
والانتهاء من ذلك:
h1 { font-size: 2vw; }
لكن هذا لا ينجح إلا إذا أخذت لوحاتك الفنية الإبداعية ذلك في الحسبان. هل اختار المصمم حجم نص يمثل بالضبط 2٪ من عرض كل من لوحاته الفنية؟ بالطبع لا. لنحسب قيمة vw
لكل نقطة توقف لدينا:
حجم 22 بكسل @ 576px
عرضًا = 22 576 * 100 = 22px
حجم 24 24px
@ 768 768px
عرضًا = 24 768 * 100 = 34px
حجم 34 بكسل @ 992px
عرض = 34 992 * 100 = 3.43vw
إنهم قريبون لكنهم ليسوا جميعًا متشابهين. لذلك ستظل بحاجة إلى استخدام استعلامات الوسائط للانتقال بين أحجام النص وستظل هناك قفزات. واعتبر هذا الأثر الجانبي الغريب:
@ 767 بكسل ، يبلغ 3.82٪ من عرض منفذ العرض 29 بكسل. إذا كان إطار العرض أعرض بمقدار 1 بكسل ، فإن font-size
ينخفض بشكل مفاجئ إلى 24 بكسل . توضح هذه الرسوم المتحركة لإطار العرض الذي يتم تغيير حجمه هذا التأثير الجانبي غير المرغوب فيه:
هذا التغيير الدراماتيكي في حجم الخط ليس بالتأكيد ما كان يتصوره المصمم. حسنا، كيف لنا ان نحل هذه المشكلة؟
الانحدار الخطي الإحصائي؟
انتظر. لما؟ نعم ، هذا مقال عن CSS ، لكن بعض الرياضيات الأساسية يمكن أن تقطع شوطًا طويلاً نحو حل أنيق لمشكلتنا.
أولاً ، دعنا نرسم قراراتنا وأحجام النص المقابلة على الرسم البياني:
هنا يمكنك رؤية مخطط مبعثر لأحجام النص المحددة من المصمم عند عرض منفذ العرض المحدد. المحور س هو عرض منفذ العرض والمحور ص هو font-size
. انظر هذا الخط؟ هذا يسمى خط الاتجاه . إنها طريقة للعثور على قيمة font-size
محرف لأي عرض لإطار العرض ، بناءً على البيانات المقدمة.
خط الاتجاه هو مفتاح كل هذا
إذا كان بإمكانك تعيين font-size
وفقًا لخط الاتجاه هذا ، فسيكون لديك h1 يتدرج بسلاسة في جميع الدقة التي تقترب من مطابقة ما قصده المصمم. أولاً ، لنلق نظرة على الرياضيات. يتم تعريف الخط المستقيم بهذه المعادلة:
- م = المنحدر
- ب = تقاطع ص
- x = عرض منفذ العرض الحالي
- y =
font-size
الناتج
هناك عدة طرق لتحديد الميل وتقاطع y. عندما يتم تضمين قيم متعددة ، فإن الطريقة الشائعة هي ملاءمة المربعات الصغرى:
بمجرد تشغيل هذه الحسابات ، يكون لديك معادلة خط الاتجاه.
كيف يمكنني استخدام هذا في CSS؟
حسنًا ، هذا يزداد صعوبة في الرياضيات. كيف نستخدم هذه الأشياء بالفعل في تطوير الويب للواجهة الأمامية؟ الجواب هو CSS calc()
! مرة أخرى ، تقنية CSS جديدة إلى حد ما مدعومة جيدًا.
يمكنك استخدام معادلة خط الاتجاه مثل هذا:
h1 { font-size: calc({slope}*100vw + {y-intercept}px); }
بمجرد العثور على المنحدر وتقاطع y ، ما عليك سوى توصيلهما!
ملاحظة: يجب عليك ضرب الميل في 100
لأنك تستخدمه كوحدة vw
1/100 من عرض منفذ العرض.
هل يمكن أتمتة هذا؟
لقد قمت بنقل طريقة ملائمة المربعات الصغرى إلى وظيفة Sass سهلة الاستخدام:
/// least-squares-fit /// Calculate the least square fit linear regression of provided values /// @param {map} $map - A Sass map of viewport width and size value combinations /// @return Linear equation as a calc() function /// @example /// font-size: least-squares-fit((576px: 24px, 768px: 24px, 992px: 34px)); /// @author Jake Wilson <[email protected]> @function least-squares-fit($map) { // Get the number of provided breakpoints $length: length(map-keys($map)); // Error if the number of breakpoints is < 2 @if ($length < 2) { @error "leastSquaresFit() $map must be at least 2 values" } // Calculate the Means $resTotal: 0; $valueTotal: 0; @each $res, $value in $map { $resTotal: $resTotal + $res; $valueTotal: $valueTotal + $value; } $resMean: $resTotal/$length; $valueMean: $valueTotal/$length; // Calculate some other stuff $multipliedDiff: 0; $squaredDiff: 0; @each $res, $value in $map { // Differences from means $resDiff: $res - $resMean; $valueDiff: $value - $valueMean; // Sum of multiplied differences $multipliedDiff: $multipliedDiff + ($resDiff * $valueDiff); // Sum of squared resolution differences $squaredDiff: $squaredDiff + ($resDiff * $resDiff); } // Calculate the Slope $m: $multipliedDiff / $squaredDiff; // Calculate the Y-Intercept $b: $valueMean - ($m * $resMean); // Return the CSS calc equation @return calc(#{$m*100}vw + #{$b}); }
هل هذا حقا يعمل؟ افتح برنامج CodePen هذا وقم بتغيير حجم نافذة المتصفح. إنها تعمل! أحجام الخطوط قريبة إلى حد ما مما كان يطلبه التصميم الأصلي ويتم تغيير حجمها بسلاسة مع التخطيط الخاص بك.
الآن ، باعتراف الجميع ، ليست مثالية. القيم قريبة من التصميم الأصلي لكنها غير متطابقة تمامًا. وذلك لأن خط الاتجاه الخطي عبارة عن تقريب لأحجام خطوط معينة عند عرض محدد لإطار العرض. هذا هو وراثة الانحدار الخطي. هناك دائما بعض الأخطاء في نتائجك. إنها مقايضة بين البساطة والدقة. أيضًا ، ضع في اعتبارك أنه كلما كانت أحجام النص أكثر تنوعًا ، زاد الخطأ في خط الاتجاه الخاص بك.
هل يمكننا أن نفعل أفضل من هذا؟
تناسب المربعات الصغرى متعددة الحدود
من أجل الحصول على خط اتجاه أكثر دقة ، تحتاج إلى إلقاء نظرة على مواضيع أكثر تقدمًا ، مثل خط اتجاه الانحدار متعدد الحدود الذي قد يبدو مثل هذا:
الآن هذا هو أكثر من ذلك! أكثر دقة بكثير من خطنا المستقيم. تبدو معادلة الانحدار الأساسية متعددة الحدود كما يلي:
كلما أردت دقة المنحنى ، زادت تعقيد المعادلة. لسوء الحظ ، لا يمكنك القيام بذلك في CSS . لا تستطيع calc()
ببساطة القيام بهذا النوع من الرياضيات المتقدمة. على وجه التحديد ، لا يمكنك حساب الأس:
font-size: calc(3vw * 3vw); /* This doesn't work in CSS */
لذلك حتى تدعم calc()
هذا النوع من الرياضيات غير الخطية ، فإننا عالقون في المعادلات الخطية فقط . هل هناك أي شيء آخر يمكننا القيام به لتحسين هذا؟
نقاط التوقف والمعادلات الخطية المتعددة
ماذا لو كنا نحسب فقط خطًا مستقيمًا بين كل زوج من نقاط التوقف؟ شيء من هذا القبيل:
لذلك في هذا المثال ، 22px
الخط المستقيم بين 22 بكسل و 24px
ثم الآخر بين 24 بكسل و 34px
24px
. سيبدو Sass هكذا:
// SCSS h1 { @media (min-width:576px) { font-size: calc(???); } @media (min-width:768px) { font-size: calc(???); } }
يمكننا استخدام طريقة ملاءمة المربعات الصغرى لقيم calc()
هذه ، ولكن نظرًا لأنها مجرد خط مستقيم بين نقطتين ، فيمكن تبسيط الرياضيات بشكل كبير. تذكر معادلة الخط المستقيم؟
نظرًا لأننا نتحدث عن نقطتين فقط الآن ، فإن إيجاد الميل (م) وتقاطع ص (ب) أمر تافه:
فيما يلي وظيفة Sass لهذا:
/// linear-interpolation /// Calculate the definition of a line between two points /// @param $map - A Sass map of viewport widths and size value pairs /// @returns A linear equation as a calc() function /// @example /// font-size: linear-interpolation((320px: 18px, 768px: 26px)); /// @author Jake Wilson <[email protected]> @function linear-interpolation($map) { $keys: map-keys($map); @if (length($keys) != 2) { @error "linear-interpolation() $map must be exactly 2 values"; } // The slope $m: (map-get($map, nth($keys, 2)) - map-get($map, nth($keys, 1)))/(nth($keys, 2) - nth($keys,1)); // The y-intercept $b: map-get($map, nth($keys, 1)) - $m * nth($keys, 1); // Determine if the sign should be positive or negative $sign: "+"; @if ($b < 0) { $sign: "-"; $b: abs($b); } @return calc(#{$m*100}vw #{$sign} #{$b}); }
الآن ، ما عليك سوى استخدام وظيفة الاستيفاء الخطي على نقاط توقف متعددة في Sass الخاص بك. أيضًا ، دعنا نلقي بعض الحد الأدنى والحد الأقصى font-sizes
:
// SCSS h1 { // Minimum font-size font-size: 22px; // Font-size between 576 - 768 @media (min-width:576px) { $map: (576px: 22px, 768px: 24px); font-size: linear-interpolation($map); } // Font-size between 768 - 992 @media (min-width:768px) { $map: (768px: 24px, 992px: 34px); font-size: linear-interpolation($map); } // Maximum font-size @media (min-width:992px) { font-size: 34px; } }
ويقوم بإنشاء CSS هذا:
h1 { font-size: 22px; } @media (min-width: 576px) { h1 { font-size: calc(1.04166667vw + 16px); } } @media (min-width: 768px) { h1 { font-size: calc(4.46428571vw - 10.28571429px); } } @media (min-width: 992px) { h1 { font-size: 34px; } }
الكأس المقدسة لتحجيم CSS؟
دعونا نختتم كل هذا في مزيج Sass لطيف (للكسول والفعال!). أنا أقوم بصياغة هذه الطريقة لتحجيم السوائل المتعددة :
/// poly-fluid-sizing /// Generate linear interpolated size values through multiple break points /// @param $property - A string CSS property name /// @param $map - A Sass map of viewport unit and size value pairs /// @requires function linear-interpolation /// @requires function map-sort /// @example /// @include poly-fluid-sizing('font-size', (576px: 22px, 768px: 24px, 992px: 34px)); /// @author Jake Wilson <[email protected]> @mixin poly-fluid-sizing($property, $map) { // Get the number of provided breakpoints $length: length(map-keys($map)); // Error if the number of breakpoints is < 2 @if ($length < 2) { @error "poly-fluid-sizing() $map requires at least values" } // Sort the map by viewport width (key) $map: map-sort($map); $keys: map-keys($map); // Minimum size #{$property}: map-get($map, nth($keys,1)); // Interpolated size through breakpoints @for $i from 1 through ($length - 1) { @media (min-width:nth($keys,$i)) { $value1: map-get($map, nth($keys,$i)); $value2: map-get($map, nth($keys,($i + 1))); // If values are not equal, perform linear interpolation @if ($value1 != $value2) { #{$property}: linear-interpolation((nth($keys,$i): $value1, nth($keys,($i+1)): $value2)); } @else { #{$property}: $value1; } } } // Maxmimum size @media (min-width:nth($keys,$length)) { #{$property}: map-get($map, nth($keys,$length)); } }
يتطلب مزيج Sass هذا بعض وظائف Sass في قواعد Github التالية:
- الاستيفاء الخطي
- فرز الخريطة
- قائمة الفرز
- إزالة القائمة
سيعمل مزيج poly-fluid-sizing()
على إجراء إقحام خطي على كل زوج من عروض منفذ العرض وتعيين الحد الأدنى والحد الأقصى للحجم. يمكنك استيراد هذا إلى أي مشروع Sass والاستفادة منه بسهولة دون الحاجة إلى معرفة أي من الرياضيات وراءه. هنا هو CodePen النهائي الذي يستخدم هذه الطريقة.
ملاحظات قليلة
- من الواضح أن هذه الطريقة لا تنطبق فقط على
font-size
ولكن على أي خاصية للوحدة / الطول (margin
،padding
، إلخ). تقوم بتمرير اسم الخاصية المطلوب إلى mixin كسلسلة. - يمكن تمرير خريطة Sass الخاصة بعرض منفذ العرض + أزواج قيمة الحجم بأي ترتيب في
poly-fluid-sizing()
. سيقوم تلقائيًا بفرز الخريطة وفقًا لعرض منفذ العرض من الأدنى إلى الأعلى . لذا يمكنك المرور في خريطة مثل هذه وستنجح على ما يرام:
$map: (576px: 22px, 320px: 18px, 992px: 34px, 768px: 24px); @include poly-fluid-sizing('font-size', $map);
- يتمثل أحد قيود هذه الطريقة في أنه لا يمكنك تمرير الوحدات المختلطة إلى المزيج. على سبيل المثال ، عرض
3em
@576px
. لن يعرف ساس حقًا ما يجب فعله رياضيًا هناك.
خاتمة
هل هذا هو أفضل ما يمكننا فعله؟ هل تحجيم السوائل المتعددة هي الكأس المقدسة لتحجيم وحدة السوائل في CSS؟ يمكن. تدعم CSS حاليًا الرسوم المتحركة غير الخطية ووظائف توقيت الانتقال ، لذلك ربما تكون هناك فرصة أن تدعمها calc()
أيضًا يومًا ما. إذا حدث ذلك ، فقد يكون الانحدار غير الخطي متعدد الحدود يستحق البحث مرة أخرى. لكن ربما لا ... قد يكون القياس الخطي أفضل على أي حال.
بدأت في استكشاف هذه الفكرة في أوائل عام 2017 ، وفي النهاية طورت الحل أعلاه. منذ ذلك الحين ، رأيت بعض المطورين يأتون بأفكار مماثلة وقطع مختلفة من هذا اللغز. اعتقدت أن الوقت قد حان لمشاركة طريقي وكيف وصلت إلى هناك. وحدات منفذ العرض. احسب (). ساس. نقاط التوقف. لا شيء من هذه الأشياء جديد. كلها ميزات متصفح موجودة منذ سنوات (بدرجات متفاوتة من الدعم). لقد استخدمتها معًا فقط بطريقة لم يتم استكشافها بالكامل بعد. لا تخف أبدًا من إلقاء نظرة على الأدوات التي تستخدمها كل يوم والتفكير خارج الصندوق في كيفية الاستفادة منها بشكل أفضل وتنمية مجموعة المهارات الخاصة بك.