Backالعودة إلى المدونة

تنسيق Next.js باستخدام Styled JSX

Styled JSX هي مكتبة CSS-in-JS تتيح لك كتابة أنماط CSS مغلقة ومحددة النطاق لتنسيق مكوناتك. سيساعدك هذا المنشور على البدء في استخدام Styled JSX مع Next.js.

Styled JSX هي مكتبة CSS-in-JS تتيح لك كتابة أنماط CSS مغلقة ومحددة النطاق لتنسيق مكوناتك. الأنماط التي تضيفها لمكون معين لن تؤثر على المكونات الأخرى، مما يسمح لك بإضافة وتغيير وحذف الأنماط دون القلق بشأن تأثيرات جانبية غير مقصودة.

البدء

Next.js يتضمن Styled JSX افتراضيًا، لذا فإن البدء بسيط مثل إضافة وسم <style jsx> إلى عنصر React موجود وكتابة CSS بداخله:

pages/index.js
function Home() {
  return (
    <div className="container">
      <h1>مرحبًا Next.js</h1>
      <p>دعنا نستكشف طرقًا مختلفة لتنسيق تطبيقات Next.js</p>
      <style jsx>{`
        .container {
          margin: 50px;
        }
        p {
          color: blue;
        }
      `}</style>
    </div>
  );
}
 
export default Home;

في هذا المثال، نقوم بتضمين أنماط لعنصر الحاوية للمكون وللفقرة. على الرغم من أننا نستخدم محددات عامة، إلا أن الأنماط لا تؤثر على العناصر ذات اسم الفئة container أو وسوم <p> في المكونات الأخرى. هذا لأن Styled JSX يضمن أن الأنماط محددة النطاق لهذا المكون فقط (من خلال تطبيق أسماء فئات فريدة إضافية على العناصر المنسقة).

بإضافة سمة jsx واحدة فقط إلى عنصر <style>، يمكنك كتابة CSS قياسي يتم تلقائيًا إضافة البادئات إليه وتحديد نطاقه للمكون. يجب وضع عناصر <style jsx> داخل العنصر الجذر للمكون.

إضافة أنماط عامة

معظم المشاريع تحتاج إلى بعض الأنماط العامة لتنسيق عنصر body أو توفير إعادة تعيين CSS. يسمح لنا Styled JSX بإضافة أنماط عامة باستخدام <style jsx global>. على سبيل المثال:

pages/index.js
function Home() {
  return (
    <div className="container">
      <h1>مرحبًا Next.js</h1>
      <p>دعنا نستكشف طرقًا مختلفة لتنسيق تطبيقات Next.js</p>
      <style jsx>{`
        .container {
          margin: 50px;
        }
        p {
          color: blue;
        }
      `}</style>
      <style jsx global>{`
        p {
          font-size: 20px;
        }
      `}</style>
    </div>
  );
}
 
export default Home;

هذا يطبق حجم خط 20 بكسل لجميع وسوم <p> في هذه الصفحة المحددة.

لتطبيق أنماط عامة على جميع الصفحات في تطبيقنا، نهج جيد هو أولاً إنشاء مكون تخطيط بالأنماط العامة، ثم تغليف جميع الصفحات به.

يوفر استخدام مكون التخطيط المرونة لتطبيق مجموعة معينة من الأنماط على بعض الصفحات مع السماح بنمط مختلف للصفحات الأخرى:

components/Layout.js
function Layout(props) {
  return (
    <div className="page-layout">
      {props.children}
      <style jsx global>{`
        body {
          margin: 0;
          padding: 0;
          font-size: 18px;
          font-weight: 400;
          line-height: 1.8;
          color: #333;
          font-family: sans-serif;
        }
        h1 {
          font-weight: 700;
        }
        p {
          margin-bottom: 10px;
        }
      `}</style>
    </div>
  );
}
 
export default Layout;

في Next.js، يمكننا تحميل التخطيط مرة واحدة لجميع الصفحات عن طريق إنشاء مكون App مخصص داخل pages/_app.js، واستيراد مكون Layout، ثم إضافته إلى طريقة العرض كما يلي:

pages/_app.js
import React from 'react';
import App, { Container } from 'next/app';
import Layout from '../components/Layout';
 
class MyApp extends App {
  render() {
    const { Component, pageProps } = this.props;
 
    return (
      <Container>
        <Layout>
          <Component {...pageProps} />
        </Layout>
      </Container>
    );
  }
}
 
export default MyApp;

كتابة الأنماط في ملفات خارجية

يمكننا أيضًا كتابة الأنماط في ملفات خارجية خارج المكون.

على سبيل المثال، يمكننا نقل الأنماط العامة من مكون Layout إلى ملف منفصل كما يلي:

styles/global.js
import css from 'styled-jsx/css';
 
export default css.global`
  body {
    margin: 0;
    padding: 0;
    font-size: 18px;
    font-weight: 400;
    line-height: 1.8;
    color: #333;
    font-family: sans-serif;
  }
  h1 {
    font-weight: 700;
  }
  p {
    margin-bottom: 10px;
  }
`;

يمكننا بعد ذلك استيراد الأنماط مرة أخرى إلى مكون Layout:

components/Layout.js
import globalStyles from '../styles/global.js';
 
function Layout(props) {
  return (
    <div className="page-layout">
      {props.children}
      <style jsx global>
        {globalStyles}
      </style>
    </div>
  );
}
 
export default Layout;

المحددات العامة لمرة واحدة

الأنماط التي نضيفها إلى مكون باستخدام <style jsx> تؤثر فقط على العناصر داخل هذا المكون، وليس المكونات الفرعية.

في بعض الأحيان، قد نحتاج إلى تجاوز نمط معين لمكون فرعي. للقيام بذلك، يوفر Styled JSX :global()، مما يوفر وصولاً إلى محددات عامة لمرة واحدة.

على سبيل المثال، لنفترض أن لدينا مكون <Widget> يحتوي على زر باسم الفئة btn. إذا أردنا تغيير ألوان هذا الزر فقط عند استيراد الودجت في الصفحة الرئيسية، يمكننا القيام بذلك كما يلي:

pages/index.js
import Widget from '../components/Widget';
 
function Home() {
  return (
    <div className="container">
      <h1>مرحبًا Next.js</h1>
      <Widget />
      <style jsx>{`
        .container {
          margin: 50px;
        }
        .container :global(.btn) {
          background: #000;
          color: #fff;
        }
      `}</style>
    </div>
  );
}
 
export default Home;

الأنماط الديناميكية

مقارنة بالحلول الأخرى، القدرة على تكييف تنسيق المكون بناءً على خصائصه هي ميزة كبيرة لمكتبات CSS-in-JS.

مع Styled JSX يمكننا القيام بذلك كما يلي:

components/Alert.js
function Alert(props) {
  return (
    <div className="alert">
      {props.children}
      <style jsx>{`
        .alert {
          display: inline-block;
          padding: 20px;
          border-radius: 8px;
        }
      `}</style>
      <style jsx>{`
        .alert {
          background: ${props.type == 'warning' ? '#fff3cd' : '#eee'};
        }
      `}</style>
    </div>
  );
}
 
export default Alert;

إذا تم تمرير خاصية type بقيمة warning إلى مكون Alert مثل:

<Alert type="warning">هذه رسالة مهمة</Alert>

سيكون للمكون خلفية برتقالية. بدون تحديد خاصية النوع، ستعود الخلفية إلى اللون الرمادي الافتراضي.

لاحظ أننا وضعنا النمط الديناميكي في وسم <style jsx> منفصل. هذا ليس مطلوبًا، ولكن يُنصح بتقسيم الأنماط الثابتة والديناميكية بحيث يتم إعادة حساب الأجزاء الديناميكية فقط عند تغيير الخصائص.

نهج بديل لتكييف الأنماط بناءً على الخصائص هو تطبيق أسماء فئات مختلفة بناءً على قيمة الخاصية كما هو موضح أدناه:

components/Alert.js
function Alert(props) {
  return (
    <div className={props.type == 'warning' ? 'alert warning' : 'alert'}>
      {props.children}
      <style jsx>{`
        .alert {
          display: inline-block;
          padding: 20px;
          border-radius: 8px;
          background: #eee;
        }
        .alert.warning {
          background: #fff3cd;
        }
      `}</style>
    </div>
  );
}
 
export default Alert;

إنشاء سمة للموقع

يمكن أن تكون السمة كائنًا بسيطًا حيث نضمّن المتغيرات الأكثر شيوعًا التي قد نحتاجها في تطبيقنا:

styles/theme.js
const theme = {
  fontFamily: {
    sansSerif: '-apple-system, "Helvetica Neue", Arial, sans-serif',
    mono: 'Menlo, Monaco, monospace',
  },
  colors: {
    text: '#333',
    background: '#fff',
    link: '#1eaaf1',
    linkHover: '#0d8ecf',
    border: '#ddd',
    warning: '#fff3cd',
    success: '#d4edda',
  },
};
 
export default theme;

ثم نستورد ملف السمة هذا في مكوناتنا ونستبدل القيم الثابتة بمتغيرات:

components/Layout.js
import theme from '../styles/theme';
 
function Layout(props) {
  return (
    <div className="page-wrapper">
      {props.children}
      <style jsx global>{`
        body {
          background: ${theme.colors.background};
          color: ${theme.colors.text};
          font-family: ${theme.fontFamily.sansSerif};
        }
      `}</style>
      <style jsx global>{`
        body {
          margin: 0;
          padding: 0;
          font-size: 18px;
          font-weight: 400;
          line-height: 1.8;
        }
        h1 {
          font-weight: 700;
        }
        p {
          margin-bottom: 10px;
        }
      `}</style>
    </div>
  );
}
 
export default Layout;
components/Alert.js
import theme from '../styles/theme';
 
function Alert(props) {
  return (
    <div className="alert">
      {props.children}
      <style jsx>{`
        .alert {
          display: inline-block;
          padding: 20px;
          border-radius: 8px;
        }
      `}</style>
      <style jsx>{`
        .alert {
          background: ${props.type == 'warning'
            ? theme.colors.warning
            : theme.colors.light};
        }
      `}</style>
    </div>
  );
}
 
export default Alert;

في هذا المنشور، غطينا كيفية البدء مع Styled JSX. لمعرفة المزيد عن الميزات الإضافية، تأكد من الاطلاع عليها على GitHub.