Next.js

Styling في Next.js — دليل شامل 2026

📅 2026-11-17⏱ 8 دقائق قراءة
في المقال السابق، تعلمت API Routes. الآن سنتعلم **Styling** — كيف نُجمّل تطبيقات Next.js باحترافية. في هذا الدليل العملي، سنأخذك خطوة بخطوة لفهم خيارات التصميم في Next.js، مع تمارين وحلول. ## خيارات Styling في Next.js <table> <thead> <tr> <th>الطريقة</th> <th>المميزات</th> <th>العيوب</th> </tr> </thead> <tbody> <tr> <td><strong>Tailwind CSS</strong></td> <td>سريع، Utility-first</td> <td>HTML مزدحم</td> </tr> <tr> <td><strong>CSS Modules</strong></td> <td>عزل، بدون تعارض</td> <td>ملفات منفصلة</td> </tr> <tr> <td><strong>Global CSS</strong></td> <td>بسيط</td> <td>تعارض محتمل</td> </tr> <tr> <td><strong>Styled Components</strong></td> <td>CSS in JS</td> <td>Bundle أكبر</td> </tr> <tr> <td><strong>Sass/SCSS</strong></td> <td>ميزات متقدمة</td> <td>يحتاج إعداد</td> </tr> </tbody> </table> **التوصية:** **Tailwind CSS** (الأكثر شيوعاً مع Next.js). ## Tailwind CSS **Tailwind** هو إطار **Utility-first** — أنماط جاهزة تُدمج في HTML. ### 1. الإعداد (تم مع create-next-app) ```bash npx create-next-app@latest my-app --tailwind ``` ### 2. `tailwind.config.ts` ```typescript import type { Config } from "tailwindcss"; const config: Config = { content: [ "./app/**/*.{js,ts,jsx,tsx,mdx}", "./components/**/*.{js,ts,jsx,tsx,mdx}", ], theme: { extend: { colors: { primary: "#3b82f6", secondary: "#8b5cf6", }, fontFamily: { cairo: ["Cairo", "sans-serif"], }, }, }, plugins: [], }; export default config; ``` ### 3. `app/globals.css` ```css @tailwind base; @tailwind components; @tailwind utilities; ``` ### 4. استخدام Tailwind ```tsx export default function Home() { return ( <div className="min-h-screen bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center"> <div className="bg-white p-12 rounded-2xl shadow-2xl text-center"> <h1 className="text-4xl font-bold text-gray-900 mb-4"> مرحباً بالعالم! </h1> <p className="text-gray-600 text-lg"> Tailwind CSS يعمل! </p> <button className="mt-6 bg-blue-600 text-white px-8 py-3 rounded-lg font-bold hover:bg-blue-700 transition"> ابدأ </button> </div> </div> ); } ``` ## أساسيات Tailwind ### 1. الألوان ```tsx <div className="bg-red-500 text-white"> <div className="bg-blue-600 text-blue-100"> <div className="bg-gradient-to-r from-pink-500 to-purple-600"> ``` ### 2. المسافات (Padding/Margin) ```tsx <div className="p-4"> {/* padding 1rem */} <div className="px-6 py-3"> {/* padding أفقي وعمودي */} <div className="m-4"> {/* margin */} <div className="mt-8 mb-4"> {/* margin أعلى وأسفل */} <div className="mx-auto"> {/* margin تلقائي */} ``` ### 3. الأحجام ```tsx <div className="w-full"> {/* عرض كامل */} <div className="w-64"> {/* 16rem */} <div className="h-screen"> {/* ارتفاع الشاشة */} <div className="max-w-4xl"> {/* أقصى عرض */} <div className="min-h-screen"> {/* أدنى ارتفاع */} ``` ### 4. Flexbox ```tsx <div className="flex items-center justify-between gap-4"> <div className="flex flex-col items-center"> <div className="flex-1"> ``` ### 5. Grid ```tsx <div className="grid grid-cols-3 gap-6"> <div className="grid md:grid-cols-2 lg:grid-cols-4 gap-4"> ``` ### 6. النصوص ```tsx <h1 className="text-4xl font-bold text-gray-900"> <p className="text-base text-gray-600 leading-relaxed"> <p className="text-sm text-gray-500 truncate"> ``` ### 7. الحدود والظلال ```tsx <div className="border border-gray-200 rounded-lg"> <div className="border-2 border-blue-500 rounded-full"> <div className="shadow-md"> <div className="shadow-lg hover:shadow-xl"> ``` ### 8. الحالات (States) ```tsx <button className="bg-blue-600 hover:bg-blue-700 active:bg-blue-800 focus:ring-2 focus:ring-blue-400"> <input className="border focus:border-blue-500 focus:outline-none"> <div className="opacity-50 disabled:opacity-100"> ``` ### 9. التجاوب (Responsive) ```tsx <div className="w-full md:w-1/2 lg:w-1/3"> <p className="text-sm md:text-base lg:text-lg"> <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4"> ``` **النقاط (Breakpoints):** - `sm`: 640px - `md`: 768px - `lg`: 1024px - `xl`: 1280px - `2xl`: 1536px ### 10. الوضع الداكن ```tsx <div className="bg-white dark:bg-gray-900"> <p className="text-gray-900 dark:text-white"> ``` ## CSS Modules **CSS Modules** هي طريقة لعزل الأنماط. ### 1. إنشاء ملف CSS **`app/components/Button.module.css`:** ```css .button { padding: 12px 24px; border-radius: 8px; font-weight: bold; cursor: pointer; transition: all 0.3s; } .primary { background: #3b82f6; color: white; } .primary:hover { background: #2563eb; } .secondary { background: #e5e7eb; color: #1f2937; } ``` ### 2. استخدامها **`app/components/Button.tsx`:** ```tsx import styles from "./Button.module.css"; export default function Button({ children, variant = "primary" }: any) { return ( <button className={`${styles.button} ${styles[variant]}`}> {children} </button> ); } ``` **الفائدة:** الأنماط **معزولة** — لا تعارض. ## Global CSS **`app/globals.css`:** ```css @tailwind base; @tailwind components; @tailwind utilities; /* أنماط عامة */ :root { --primary: #3b82f6; --secondary: #8b5cf6; } body { font-family: 'Cairo', sans-serif; direction: rtl; } /* Component classes */ .btn { padding: 12px 24px; border-radius: 8px; font-weight: bold; } ``` **الاستخدام:** ```tsx <button className="btn bg-blue-600 text-white">اضغط</button> ``` ## Tailwind مع clsx **`clsx`** تسهّل دمج الأنماط الشرطية. ```bash npm install clsx ``` ```tsx import clsx from "clsx"; interface ButtonProps { variant?: "primary" | "secondary"; size?: "sm" | "lg"; } export default function Button({ variant = "primary", size = "sm", }: ButtonProps) { return ( <button className={clsx( "rounded-lg font-bold transition", variant === "primary" && "bg-blue-600 text-white hover:bg-blue-700", variant === "secondary" && "bg-gray-200 text-gray-800 hover:bg-gray-300", size === "sm" && "px-4 py-2 text-sm", size === "lg" && "px-8 py-4 text-lg" )} > اضغط </button> ); } ``` ## Tailwind مع cn (clsx + tailwind-merge) ```bash npm install clsx tailwind-merge ``` **`lib/utils.ts`:** ```typescript import { clsx, type ClassValue } from "clsx"; import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } ``` **الاستخدام:** ```tsx import { cn } from "@/lib/utils"; <div className={cn("p-4 bg-blue-500", isActive && "bg-red-500")} /> ``` **الفائدة:** Tailwind-merge يحل تعارض الأنماط. ## الخطوط (Fonts) Next.js يدعم **next/font** للخطوط. ```tsx // app/layout.tsx import { Cairo, Tajawal } from "next/font/google"; const cairo = Cairo({ subsets: ["arabic", "latin"], weight: ["400", "600", "700", "900"], variable: "--font-cairo", }); const tajawal = Tajawal({ subsets: ["arabic"], weight: ["400", "500", "700"], variable: "--font-tajawal", }); export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="ar" dir="rtl" className={`${cairo.variable} ${tajawal.variable}`}> <body className="font-cairo">{children}</body> </html> ); } ``` **`tailwind.config.ts`:** ```typescript theme: { extend: { fontFamily: { cairo: ["var(--font-cairo)", "sans-serif"], tajawal: ["var(--font-tajawal)", "sans-serif"], }, }, }, ``` ## الخطوط المحلية ```tsx import localFont from "next/font/local"; const myFont = localFont({ src: "./fonts/MyFont.woff2", variable: "--font-my", }); ``` ## مثال عملي: بطاقة منتج ```tsx export default function ProductCard({ product }: any) { return ( <div className="bg-white rounded-2xl shadow-sm overflow-hidden hover:shadow-lg transition group"> <div className="relative h-64 overflow-hidden"> <img src={product.image} alt={product.name} className="w-full h-full object-cover group-hover:scale-105 transition duration-300" /> </div> <div className="p-6"> <span className="inline-block bg-blue-100 text-blue-700 text-xs px-3 py-1 rounded-full mb-3"> {product.category} </span> <h3 className="text-xl font-bold text-gray-900 mb-2"> {product.name} </h3> <p className="text-gray-600 text-sm mb-4"> {product.description} </p> <div className="flex items-center justify-between"> <span className="text-2xl font-bold text-blue-600"> {product.price} $ </span> <button className="bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition"> أضف للسلة </button> </div> </div> </div> ); } ``` ## تمارين عملية ### تمرين 1: Hero Section أنشئ قسم بطل بتدرج. **الحل:** ```tsx <section className="min-h-screen bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center text-white"> <div className="text-center"> <h1 className="text-6xl font-bold mb-4">مرحباً</h1> <p className="text-xl opacity-90">تطبيقي الأول</p> </div> </section> ``` ### تمرين 2: Navbar أنشئ شريط تنقل. **الحل:** ```tsx <nav className="bg-white shadow-sm sticky top-0 z-50"> <div className="max-w-6xl mx-auto px-4 py-4 flex items-center justify-between"> <span className="text-2xl font-bold text-blue-600">شعاري</span> <ul className="flex gap-6"> <li><a href="/" className="text-gray-700 hover:text-blue-600">الرئيسية</a></li> <li><a href="/about" className="text-gray-700 hover:text-blue-600">من نحن</a></li> </ul> </div> </nav> ``` ### تمرين 3: بطاقات Grid أنشئ شبكة بطاقات. **الحل:** ```tsx <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 p-8"> {items.map((item) => ( <div key={item.id} className="bg-white p-6 rounded-2xl shadow-sm"> <h3 className="text-xl font-bold mb-2">{item.title}</h3> <p className="text-gray-600">{item.description}</p> </div> ))} </div> ``` ### تمرين 4: زر بحالات أنشئ زر مع hover/focus. **الحل:** ```tsx <button className="bg-blue-600 text-white px-6 py-3 rounded-lg font-bold hover:bg-blue-700 active:bg-blue-800 focus:ring-2 focus:ring-blue-400 focus:ring-offset-2 transition disabled:opacity-50 disabled:cursor-not-allowed"> اضغط </button> ``` ### تمرين 5: CSS Module أنشئ مكون Button مع CSS Module. **الحل:** ```css /* Button.module.css */ .button { padding: 12px 24px; border-radius: 8px; font-weight: bold; } .primary { background: #3b82f6; color: white; } ``` ```tsx import styles from "./Button.module.css"; export default function Button() { return <button className={`${styles.button} ${styles.primary}`}>اضغط</button>; } ``` ### تمرين 6: Responsive Grid أنشئ Grid متجاوب. **الحل:** ```tsx <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4"> {/* items */} </div> ``` ### تمرين 7: Dark Mode أضف الوضع الداكن. **الحل:** ```tsx <div className="bg-white dark:bg-gray-900 text-gray-900 dark:text-white"> <p className="text-gray-600 dark:text-gray-300">نص</p> </div> ``` ### تمرين 8: صفحة كاملة صمم صفحة كاملة بـ Tailwind. **الحل:** (راجع بطاقة المنتج) ## حل المشاكل الشائعة ### 🔴 المشكلة 1: Tailwind لا يعمل **السبب:** لم يُضف `@tailwind` في `globals.css`. **الحل:** ```css @tailwind base; @tailwind components; @tailwind utilities; ``` ### 🔴 المشكلة 2: الأنماط لا تُطبَّق **السبب:** `content` في `tailwind.config.ts` ناقص. **الحل:** ```typescript content: [ "./app/**/*.{js,ts,jsx,tsx,mdx}", "./components/**/*.{js,ts,jsx,tsx,mdx}", ], ``` ### 🔴 المشكلة 3: الخط العربي لا يظهر **السبب:** لم تُضف `subsets: ["arabic"]`. **الحل:** ```tsx const cairo = Cairo({ subsets: ["arabic", "latin"], weight: ["400", "700"], }); ``` ### 🔴 المشكلة 4: CSS Module لا يعمل **السبب:** اسم الملف خاطئ. **الحل:** يجب أن يكون `Component.module.css`. ### 🔴 المشكلة 5: Dark Mode لا يعمل **السبب:** لم تُفعّل في `tailwind.config.ts`. **الحل:** ```typescript darkMode: "class", ``` ## جدول خصائص Tailwind <table> <thead> <tr> <th>الخاصية</th> <th>الأمثلة</th> </tr> </thead> <tbody> <tr> <td><strong>Padding</strong></td> <td><code>p-4</code>, <code>px-6</code>, <code>py-3</code></td> </tr> <tr> <td><strong>Margin</strong></td> <td><code>m-4</code>, <code>mt-8</code>, <code>mx-auto</code></td> </tr> <tr> <td><strong>Text</strong></td> <td><code>text-xl</code>, <code>font-bold</code>, <code>text-blue-600</code></td> </tr> <tr> <td><strong>Background</strong></td> <td><code>bg-white</code>, <code>bg-gray-100</code></td> </tr> <tr> <td><strong>Border</strong></td> <td><code>border</code>, <code>border-2</code>, <code>rounded-lg</code></td> </tr> <tr> <td><strong>Flex</strong></td> <td><code>flex</code>, <code>items-center</code>, <code>justify-between</code></td> </tr> <tr> <td><strong>Grid</strong></td> <td><code>grid</code>, <code>grid-cols-3</code>, <code>gap-4</code></td> </tr> <tr> <td><strong>Shadow</strong></td> <td><code>shadow-sm</code>, <code>shadow-lg</code></td> </tr> <tr> <td><strong>Hover</strong></td> <td><code>hover:bg-blue-700</code></td> </tr> <tr> <td><strong>Responsive</strong></td> <td><code>md:</code>, <code>lg:</code>, <code>xl:</code></td> </tr> </tbody> </table> ## قائمة تحقق نهائية <table> <thead> <tr> <th>المهمة</th> <th>الحالة</th> </tr> </thead> <tbody> <tr> <td>فهم Tailwind CSS</td> <td>⬜</td> </tr> <tr> <td>استخدام Flexbox و Grid</td> <td>⬜</td> </tr> <tr> <td>التصميم المتجاوب</td> <td>⬜</td> </tr> <tr> <td>الوضع الداكن</td> <td>⬜</td> </tr> <tr> <td>CSS Modules</td> <td>⬜</td> </tr> <tr> <td>الخطوط (next/font)</td> <td>⬜</td> </tr> <tr> <td>حل التمارين الثمانية</td> <td>⬜</td> </tr> </tbody> </table> ## ماذا بعد هذا المقال؟ الآن بعد أن أتقنت Styling، أنت جاهز للمقال التالي: 1. **Authentication** — المصادقة. 2. **Deployment** — النشر. 3. **مشروع كامل** — مدونة متكاملة. ## الخلاصة في هذا المقال، تعلمت: - ✅ Tailwind CSS (الأساسيات). - ✅ CSS Modules. - ✅ Global CSS. - ✅ clsx و cn. - ✅ الخطوط مع next/font. - ✅ الوضع الداكن. - ✅ التصميم المتجاوب. - ✅ حل 8 تمارين عملية. **تذكر:** Tailwind CSS هو **الأداة الأسرع** للتصميم في Next.js.