معالج SASS/SCSS

مشروع واقعي: بناء ورقة أنماط موقع ويب كاملة

30 دقيقة الدرس 29 من 30

نظرة عامة على المشروع: ورقة أنماط موقع محفظة أعمال

في هذا الدرس العملي الشامل، سنبني ورقة أنماط كاملة وجاهزة للإنتاج لموقع محفظة أعمال/صفحة هبوط من الصفر باستخدام SASS. سيدمج هذا المشروع كل ما تعلمته خلال هذه الدورة، مع تطبيق أفضل الممارسات والبنية المناسبة والتصميم المتجاوب وتقنيات CSS الحديثة. بحلول النهاية، ستحصل على ورقة أنماط عملية وقابلة للصيانة بالكامل يمكنك استخدامها كقالب للمشاريع المستقبلية.

ملاحظة: هذا درس مكثف يحاكي سير عمل تطوير واقعي. خذ وقتك مع كل قسم وتأكد من أنك تفهم القرارات التي يتم اتخاذها.

متطلبات المشروع

سيتضمن موقع محفظتنا:

  • رأس تنقل متجاوب مع شعار وقائمة
  • قسم البطل مع دعوة إلى إجراء
  • قسم حول مع صورة ونص
  • قسم بطاقات المهارات/الخدمات
  • شبكة معرض المحفظة/المشاريع
  • قسم نموذج الاتصال
  • تذييل مع روابط اجتماعية
  • دعم تبديل الوضع الداكن
  • تصميم متجاوب (الهاتف المحمول أولاً)
  • رسوم متحركة وانتقالات سلسة

الخطوة 1: إعداد بنية المجلد 7-1

سنستخدم نمط بنية 7-1 القياسي في الصناعة لتنظيم ملفات SASS الخاصة بنا.

بنية المشروع

portfolio/
├── scss/
│   ├── abstracts/
│   │   ├── _variables.scss
│   │   ├── _mixins.scss
│   │   └── _functions.scss
│   ├── base/
│   │   ├── _reset.scss
│   │   ├── _typography.scss
│   │   └── _animations.scss
│   ├── components/
│   │   ├── _buttons.scss
│   │   ├── _card.scss
│   │   ├── _form.scss
│   │   └── _social-links.scss
│   ├── layout/
│   │   ├── _header.scss
│   │   ├── _footer.scss
│   │   ├── _navigation.scss
│   │   ├── _grid.scss
│   │   └── _section.scss
│   ├── pages/
│   │   └── _home.scss
│   ├── themes/
│   │   └── _dark-mode.scss
│   ├── vendors/
│   │   └── (أنماط طرف ثالث إذا لزم الأمر)
│   └── main.scss
├── dist/
│   └── css/
│       └── style.css
└── package.json

الخطوة 2: إنشاء ملف المتغيرات

سيحدد ملف المتغيرات الخاص بنا جميع رموز التصميم: الألوان والطباعة والتباعد ونقاط التوقف والانتقالات.

abstracts/_variables.scss

// ========================================
// نظام الألوان
// ========================================

// ألوان العلامة التجارية الأساسية
$color-primary: #6366f1;
$color-primary-light: #818cf8;
$color-primary-dark: #4f46e5;

// الألوان المحايدة
$color-white: #ffffff;
$color-black: #000000;
$color-gray-100: #f3f4f6;
$color-gray-200: #e5e7eb;
$color-gray-300: #d1d5db;
$color-gray-400: #9ca3af;
$color-gray-500: #6b7280;
$color-gray-600: #4b5563;
$color-gray-700: #374151;
$color-gray-800: #1f2937;
$color-gray-900: #111827;

// الألوان الدلالية
$color-success: #10b981;
$color-warning: #f59e0b;
$color-error: #ef4444;
$color-info: #3b82f6;

// ألوان الخلفية
$bg-light: $color-white;
$bg-light-alt: $color-gray-100;
$bg-dark: $color-gray-900;
$bg-dark-alt: $color-gray-800;

// ألوان النص
$text-light: $color-gray-900;
$text-light-secondary: $color-gray-600;
$text-dark: $color-gray-100;
$text-dark-secondary: $color-gray-400;

// ========================================
// الطباعة
// ========================================

// عائلات الخطوط
$font-primary: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
$font-heading: 'Poppins', $font-primary;
$font-mono: 'Fira Code', 'Courier New', monospace;

// أحجام الخطوط
$font-size-xs: 0.75rem;      // 12px
$font-size-sm: 0.875rem;     // 14px
$font-size-base: 1rem;       // 16px
$font-size-lg: 1.125rem;     // 18px
$font-size-xl: 1.25rem;      // 20px
$font-size-2xl: 1.5rem;      // 24px
$font-size-3xl: 1.875rem;    // 30px
$font-size-4xl: 2.25rem;     // 36px
$font-size-5xl: 3rem;        // 48px
$font-size-6xl: 3.75rem;     // 60px

// أوزان الخطوط
$font-weight-normal: 400;
$font-weight-medium: 500;
$font-weight-semibold: 600;
$font-weight-bold: 700;

// ارتفاعات الأسطر
$line-height-tight: 1.25;
$line-height-normal: 1.5;
$line-height-relaxed: 1.75;

// ========================================
// مقياس التباعد
// ========================================

$spacing-0: 0;
$spacing-1: 0.25rem;   // 4px
$spacing-2: 0.5rem;    // 8px
$spacing-3: 0.75rem;   // 12px
$spacing-4: 1rem;      // 16px
$spacing-5: 1.25rem;   // 20px
$spacing-6: 1.5rem;    // 24px
$spacing-8: 2rem;      // 32px
$spacing-10: 2.5rem;   // 40px
$spacing-12: 3rem;     // 48px
$spacing-16: 4rem;     // 64px
$spacing-20: 5rem;     // 80px
$spacing-24: 6rem;     // 96px

// ========================================
// نقاط التوقف
// ========================================

$breakpoint-sm: 640px;
$breakpoint-md: 768px;
$breakpoint-lg: 1024px;
$breakpoint-xl: 1280px;
$breakpoint-2xl: 1536px;

// خريطة نقاط التوقف لاستخدام الحلقة
$breakpoints: (
  'sm': $breakpoint-sm,
  'md': $breakpoint-md,
  'lg': $breakpoint-lg,
  'xl': $breakpoint-xl,
  '2xl': $breakpoint-2xl
);

// ========================================
// التخطيط
// ========================================

$container-max-width: 1280px;
$container-padding: $spacing-6;

$header-height: 70px;
$header-height-mobile: 60px;

// ========================================
// الحدود والنصف قطر
// ========================================

$border-width: 1px;
$border-color-light: $color-gray-200;
$border-color-dark: $color-gray-700;

$border-radius-sm: 0.25rem;   // 4px
$border-radius-base: 0.5rem;  // 8px
$border-radius-lg: 0.75rem;   // 12px
$border-radius-xl: 1rem;      // 16px
$border-radius-full: 9999px;

// ========================================
// الظلال
// ========================================

$shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
$shadow-base: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
$shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
$shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
$shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);

// ========================================
// الانتقالات
// ========================================

$transition-fast: 150ms ease-in-out;
$transition-base: 250ms ease-in-out;
$transition-slow: 350ms ease-in-out;

// ========================================
// مقياس Z-index
// ========================================

$z-index-dropdown: 1000;
$z-index-sticky: 1020;
$z-index-fixed: 1030;
$z-index-modal-backdrop: 1040;
$z-index-modal: 1050;
$z-index-popover: 1060;
$z-index-tooltip: 1070;

الخطوة 3: بناء Mixins قابلة لإعادة الاستخدام

أنشئ mixins للتصميم المتجاوب وتخطيطات flexbox والأنماط الشائعة.

abstracts/_mixins.scss

@use 'variables' as *;

// ========================================
// نقاط التوقف المتجاوبة
// ========================================

@mixin respond-to($breakpoint) {
  @if map-has-key($breakpoints, $breakpoint) {
    @media (min-width: map-get($breakpoints, $breakpoint)) {
      @content;
    }
  } @else {
    @warn "نقطة توقف غير صالحة: #{$breakpoint}";
  }
}

// نقطة توقف مخصصة
@mixin custom-breakpoint($min-width) {
  @media (min-width: $min-width) {
    @content;
  }
}

// ========================================
// أدوات Flexbox
// ========================================

@mixin flex-center {
  display: flex;
  justify-content: center;
  align-items: center;
}

@mixin flex-between {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

@mixin flex-column {
  display: flex;
  flex-direction: column;
}

// ========================================
// أدوات Grid
// ========================================

@mixin grid($columns: 3, $gap: $spacing-6) {
  display: grid;
  grid-template-columns: repeat($columns, 1fr);
  gap: $gap;
}

@mixin grid-responsive($mobile: 1, $tablet: 2, $desktop: 3, $gap: $spacing-6) {
  display: grid;
  grid-template-columns: repeat($mobile, 1fr);
  gap: $gap;

  @include respond-to('md') {
    grid-template-columns: repeat($tablet, 1fr);
  }

  @include respond-to('lg') {
    grid-template-columns: repeat($desktop, 1fr);
  }
}

// ========================================
// تحديد المواقع
// ========================================

@mixin absolute-center {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

@mixin absolute-cover {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

// ========================================
// أدوات النص
// ========================================

@mixin text-truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@mixin line-clamp($lines: 2) {
  display: -webkit-box;
  -webkit-line-clamp: $lines;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

// ========================================
// التأثيرات البصرية
// ========================================

@mixin card-shadow {
  box-shadow: $shadow-base;
  transition: box-shadow $transition-base;

  &:hover {
    box-shadow: $shadow-lg;
  }
}

@mixin focus-ring($color: $color-primary) {
  outline: 2px solid transparent;
  outline-offset: 2px;

  &:focus-visible {
    outline-color: $color;
  }
}

الخطوة 4: الأنماط الأساسية

أعد الأساس بإعادة التعيين والطباعة والأنماط العامة.

base/_reset.scss

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

body {
  min-height: 100vh;
  line-height: 1.5;
}

img,
picture,
video,
canvas,
svg {
  display: block;
  max-width: 100%;
}

input,
button,
textarea,
select {
  font: inherit;
}

p,
h1,
h2,
h3,
h4,
h5,
h6 {
  overflow-wrap: break-word;
}

ul,
ol {
  list-style: none;
}

a {
  text-decoration: none;
  color: inherit;
}

base/_typography.scss

@use '../abstracts' as *;

body {
  font-family: $font-primary;
  font-size: $font-size-base;
  font-weight: $font-weight-normal;
  line-height: $line-height-normal;
  color: $text-light;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: $font-heading;
  font-weight: $font-weight-bold;
  line-height: $line-height-tight;
  margin-bottom: $spacing-4;
}

h1 {
  font-size: $font-size-4xl;

  @include respond-to('md') {
    font-size: $font-size-5xl;
  }

  @include respond-to('lg') {
    font-size: $font-size-6xl;
  }
}

h2 {
  font-size: $font-size-3xl;

  @include respond-to('md') {
    font-size: $font-size-4xl;
  }
}

h3 {
  font-size: $font-size-2xl;

  @include respond-to('md') {
    font-size: $font-size-3xl;
  }
}

h4 {
  font-size: $font-size-xl;
}

h5 {
  font-size: $font-size-lg;
}

h6 {
  font-size: $font-size-base;
}

p {
  margin-bottom: $spacing-4;

  &:last-child {
    margin-bottom: 0;
  }
}

.lead {
  font-size: $font-size-lg;
  color: $text-light-secondary;

  @include respond-to('md') {
    font-size: $font-size-xl;
  }
}

الخطوة 5: بناء المكونات

أنشئ أنماط مكونات قابلة لإعادة الاستخدام للأزرار والبطاقات والنماذج.

components/_buttons.scss

@use '../abstracts' as *;

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: $spacing-2;
  padding: $spacing-3 $spacing-6;
  font-weight: $font-weight-medium;
  border-radius: $border-radius-base;
  border: $border-width solid transparent;
  cursor: pointer;
  transition: all $transition-base;
  @include focus-ring;

  &:disabled {
    opacity: 0.6;
    cursor: not-allowed;
  }
}

.btn-primary {
  background-color: $color-primary;
  color: $color-white;

  &:hover:not(:disabled) {
    background-color: $color-primary-dark;
    transform: translateY(-2px);
    box-shadow: $shadow-md;
  }

  &:active:not(:disabled) {
    transform: translateY(0);
  }
}

.btn-secondary {
  background-color: transparent;
  color: $color-primary;
  border-color: $color-primary;

  &:hover:not(:disabled) {
    background-color: $color-primary;
    color: $color-white;
  }
}

.btn-ghost {
  background-color: transparent;
  color: $text-light;

  &:hover:not(:disabled) {
    background-color: $color-gray-100;
  }
}

.btn-lg {
  padding: $spacing-4 $spacing-8;
  font-size: $font-size-lg;
}

.btn-sm {
  padding: $spacing-2 $spacing-4;
  font-size: $font-size-sm;
}

components/_card.scss

@use '../abstracts' as *;

.card {
  background-color: $bg-light;
  border-radius: $border-radius-lg;
  padding: $spacing-6;
  @include card-shadow;

  &__image {
    width: 100%;
    height: 200px;
    object-fit: cover;
    border-radius: $border-radius-base;
    margin-bottom: $spacing-4;
  }

  &__title {
    font-size: $font-size-xl;
    margin-bottom: $spacing-3;
  }

  &__text {
    color: $text-light-secondary;
    margin-bottom: $spacing-4;
  }

  &__footer {
    @include flex-between;
    padding-top: $spacing-4;
    border-top: $border-width solid $border-color-light;
  }
}

الخطوة 6: مكونات التخطيط

layout/_header.scss

@use '../abstracts' as *;

.header {
  position: sticky;
  top: 0;
  z-index: $z-index-sticky;
  background-color: $bg-light;
  border-bottom: $border-width solid $border-color-light;
  backdrop-filter: blur(10px);
  background-color: rgba(255, 255, 255, 0.9);

  &__container {
    max-width: $container-max-width;
    margin: 0 auto;
    padding: 0 $container-padding;
    @include flex-between;
    height: $header-height-mobile;

    @include respond-to('md') {
      height: $header-height;
    }
  }

  &__logo {
    font-size: $font-size-xl;
    font-weight: $font-weight-bold;
    color: $color-primary;
  }

  &__nav {
    display: none;

    @include respond-to('md') {
      display: flex;
      gap: $spacing-8;
    }
  }

  &__nav-link {
    font-weight: $font-weight-medium;
    transition: color $transition-base;

    &:hover {
      color: $color-primary;
    }
  }
}

الخطوة 7: تطبيق التصميم المتجاوب

طبّق التصميم المتجاوب للهاتف المحمول أولاً في جميع أنحاء المشروع.

pages/_home.scss

@use '../abstracts' as *;

.hero {
  padding: $spacing-16 $container-padding;
  text-align: center;

  @include respond-to('lg') {
    padding: $spacing-24 $container-padding;
  }

  &__title {
    margin-bottom: $spacing-6;
    background: linear-gradient(135deg, $color-primary 0%, $color-primary-light 100%);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
  }

  &__buttons {
    display: flex;
    flex-direction: column;
    gap: $spacing-4;
    max-width: 400px;
    margin: 0 auto;

    @include respond-to('sm') {
      flex-direction: row;
      justify-content: center;
    }
  }
}

.skills {
  padding: $spacing-20 $container-padding;
  background-color: $bg-light-alt;

  &__grid {
    max-width: $container-max-width;
    margin: 0 auto;
    @include grid-responsive($mobile: 1, $tablet: 2, $desktop: 3);
  }
}

الخطوة 8: دعم الوضع الداكن

themes/_dark-mode.scss

@use '../abstracts' as *;

[data-theme="dark"] {
  color-scheme: dark;

  body {
    background-color: $bg-dark;
    color: $text-dark;
  }

  .header {
    background-color: rgba(17, 24, 39, 0.9);
    border-bottom-color: $border-color-dark;
  }

  .card {
    background-color: $bg-dark-alt;
    color: $text-dark;
  }

  .btn-ghost {
    color: $text-dark;

    &:hover:not(:disabled) {
      background-color: $color-gray-800;
    }
  }

  .skills {
    background-color: $bg-dark-alt;
  }
}

الخطوة 9: الترجمة النهائية والتحسين

main.scss - ملف الدخول الرئيسي

// التجريدات
@use 'abstracts/variables';
@use 'abstracts/mixins';
@use 'abstracts/functions';

// الأساس
@use 'base/reset';
@use 'base/typography';
@use 'base/animations';

// التخطيط
@use 'layout/header';
@use 'layout/footer';
@use 'layout/navigation';
@use 'layout/grid';
@use 'layout/section';

// المكونات
@use 'components/buttons';
@use 'components/card';
@use 'components/form';
@use 'components/social-links';

// الصفحات
@use 'pages/home';

// الثيمات
@use 'themes/dark-mode';

package.json - سكريبتات البناء

{
  "scripts": {
    "dev": "sass --watch scss/main.scss:dist/css/style.css --source-map",
    "build": "sass scss/main.scss:dist/css/style.css --style=compressed --no-source-map",
    "build:dev": "sass scss/main.scss:dist/css/style.css --style=expanded --source-map"
  }
}

تمرين 1: إكمال المشروع

ابنِ ورقة أنماط المحفظة الكاملة:

  1. أعد بنية المجلد 7-1
  2. أنشئ جميع الملفات الموضحة في هذا الدرس
  3. أضف مكون تذييل مع روابط اجتماعية
  4. أنشئ مكون نموذج اتصال
  5. نفّذ رسوم متحركة للتمرير السلس
  6. اختبر تبديل الوضع الداكن
  7. تحقق من التصميم المتجاوب على جميع نقاط التوقف
  8. بناء للإنتاج والتحقق من حجم ملف الإخراج

تمرين 2: توسيع المشروع

أضف هذه الميزات الإضافية:

  1. أنشئ مكون بطاقة مدونة لقسم المدونة
  2. أضف قسم دائري للشهادات
  3. نفّذ قائمة همبرجر لتنقل الهاتف المحمول
  4. أضف تأثيرات التمرير والانتقالات لجميع العناصر التفاعلية
  5. أنشئ فئات مساعدة للتباعد والألوان والطباعة

تمرين 3: التحسين والتدقيق

حسّن ورقة الأنماط الخاصة بك:

  1. قم بتشغيل أمر البناء والتحقق من حجم ملف CSS
  2. استخدم محلل CSS لتحديد الأنماط غير المستخدمة
  3. أزل أي كود زائد أو متغيرات غير مستخدمة
  4. أعد PostCSS مع autoprefixer و cssnano
  5. اختبر البناء النهائي في متصفحات متعددة
  6. وثّق نظام الألوان وواجهة برمجة تطبيقات المكونات