0Pricing
React Native Academy · درس

‏StyleSheet.create والأنماط المضمّنة

أنشئ كائنات الأنماط باستخدام StyleSheet.create لتحسين الأداء، وقارنها بالأنماط المضمّنة، وطبّق عدة أنماط باستخدام المصفوفات.

‏StyleSheet.create والأنماط المضمّنة درس مجاني في React Native Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في React Native Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة React Native Academy 4 دروس في المجموع.

بعض أجزاء هذا الدرس لم تُترجم بعد وتظهر باللغة الإنجليزية.

How React Native Styles Work

React Native styling is inspired by CSS but uses JavaScript objects instead of CSS files. Property names are camelCase (backgroundColor not background-color), and values for lengths and sizes are numbers representing device-independent pixels — not strings like '16px'. There are no selectors, cascading, or inheritance (except font styles inside nested Text components). Each component is styled individually through a style prop, giving you explicit control over every element's appearance.

import { View, Text } from 'react-native';

export default function StyledBox() {
  return (
    // Inline style object directly
    <View style={{
      width: 120,
      height: 120,
      backgroundColor: '#4f86f7',
      borderRadius: 16,
      padding: 16,
    }}>
      <Text style={{ color: '#fff', fontSize: 18, fontWeight: 'bold' }}>
        Hello!
      </Text>
    </View>
  );
}

StyleSheet.create() for Performance

StyleSheet.create() takes an object of named style definitions and returns a processed version. Under the hood, React Native registers these styles with the native layer and sends only an integer ID during subsequent renders, rather than the full style object. This reduces the JavaScript-to-native communication overhead — especially noticeable in lists that re-render frequently. It also runs style validation in development mode, warning you if you use unsupported properties. Always prefer StyleSheet.create over inline objects for styles that don't change.

import { View, Text, StyleSheet } from 'react-native';

export default function Card() {
  return (
    <View style={styles.card}>
      <Text style={styles.title}>Card Title</Text>
      <Text style={styles.body}>Card description text goes here.</Text>
    </View>
  );
}

// Defined once, referenced by name
const styles = StyleSheet.create({
  card: {
    backgroundColor: '#fff',
    borderRadius: 12,
    padding: 16,
    marginBottom: 12,
    elevation: 3,
  },
  title: { fontSize: 18, fontWeight: 'bold', color: '#222' },
  body: { fontSize: 14, color: '#666', marginTop: 6, lineHeight: 20 },
});

Inline Styles: When to Use Them

Inline styles are written directly in the JSX as a JavaScript object literal: style={{ color: 'red' }}. They are recreated on every render, which is slightly less efficient than StyleSheet.create styles. However, inline styles are appropriate when the style value is dynamic — computed from props or state at runtime. For example, setting backgroundColor based on a user's chosen theme color or computing width from the current component state. In these cases, StyleSheet.create cannot help because the value changes at runtime.

import { View } from 'react-native';

// Inline style: backgroundColor is dynamic (from props)
function ColoredBox({ color, size }) {
  return (
    <View
      style={{
        backgroundColor: color,  // dynamic — must be inline
        width: size,             // dynamic — must be inline
        height: size,
        borderRadius: size / 2,
      }}
    />
  );
}

// Usage:
<ColoredBox color='#ff6b6b' size={80} />
<ColoredBox color='#4f86f7' size={40} />

Combining Static and Dynamic Styles

React Native's style prop accepts an array of style objects. Later styles in the array override earlier ones for the same property (like specificity in CSS, but simpler). This lets you combine a base style from StyleSheet.create with dynamic inline overrides: style={[styles.box, { backgroundColor: color }]}. The static styles are efficient (only sent as IDs), while the dynamic inline object is added on top. Falsy values in the array (null, undefined, false) are safely ignored.

import { TouchableOpacity, Text, StyleSheet } from 'react-native';

export default function Button({ label, primary, style }) {
  return (
    <TouchableOpacity
      style={[
        styles.base,           // always applied
        primary && styles.primary,  // conditional style
        style,                 // caller's overrides
      ]}
    >
      <Text style={[styles.text, primary && styles.primaryText]}>
        {label}
      </Text>
    </TouchableOpacity>
  );
}

const styles = StyleSheet.create({
  base: { paddingVertical: 12, paddingHorizontal: 24, borderRadius: 24, borderWidth: 1.5, borderColor: '#4f86f7', alignItems: 'center' },
  primary: { backgroundColor: '#4f86f7', borderColor: '#4f86f7' },
  text: { color: '#4f86f7', fontWeight: '600', fontSize: 16 },
  primaryText: { color: '#fff' },
});

Common StyleSheet Properties

React Native supports a well-defined subset of CSS properties. The most frequently used ones are: layout (flex, flexDirection, justifyContent, alignItems, padding, margin, width, height), visual (backgroundColor, borderRadius, opacity), and text (fontSize, fontWeight, color, lineHeight). Properties like grid, float, display: grid, z-index (use zIndex), and CSS animations are NOT supported in React Native — use Flexbox and the Animated API instead.

const styles = StyleSheet.create({
  // Layout
  container: { flex: 1, flexDirection: 'column', justifyContent: 'center', alignItems: 'center' },
  // Box model
  box: { width: 100, height: 100, margin: 8, padding: 12 },
  // Visual
  card: { backgroundColor: '#fff', borderRadius: 12, opacity: 0.9, zIndex: 10 },
  // Borders
  bordered: { borderWidth: 1, borderColor: '#ccc', borderStyle: 'solid' },
  // Text styles (only valid on Text component)
  heading: { fontSize: 24, fontWeight: '700', color: '#333', letterSpacing: 0.5 },
});

Percentage Values in Styles

React Native supports percentage strings for width, height, and positioning properties like top, left. A width of '100%' fills the parent, '50%' takes half, and so on. Percentages are resolved relative to the parent container's size, not the screen. This is useful for full-width cards (width: '100%') and two-column layouts (width: '48%'). For the screen width itself, use the Dimensions API or the useWindowDimensions hook for responsive, dynamic values.

import { View, useWindowDimensions, StyleSheet } from 'react-native';

export default function HalfBox() {
  const { width } = useWindowDimensions();
  const cardWidth = (width - 48) / 2; // two columns with gutters

  return (
    <View style={styles.row}>
      <View style={[styles.card, { width: cardWidth }]} />
      <View style={[styles.card, { width: cardWidth }]} />
    </View>
  );
}

const styles = StyleSheet.create({
  row: { flexDirection: 'row', gap: 16, paddingHorizontal: 16 },
  card: { height: 100, backgroundColor: '#4f86f7', borderRadius: 12 },
});

StyleSheet.flatten and Style Merging

StyleSheet.flatten() accepts a style array and returns a single merged object. This is useful when you need to read the final computed style value programmatically — for example, reading the backgroundColor from a style array to pass it to an animation. It resolves array styles the same way React Native does: later values override earlier ones. Logging StyleSheet.flatten(styles) is also helpful during debugging to see exactly what styles a component will receive after all merging is done.

import { StyleSheet } from 'react-native';

const base = StyleSheet.create({
  box: { width: 100, height: 100, backgroundColor: 'blue' },
});

const override = { backgroundColor: 'red', borderRadius: 12 };

// Merge and inspect the final style
const final = StyleSheet.flatten([base.box, override]);
console.log(final);
// {
//   width: 100,
//   height: 100,
//   backgroundColor: 'red',   ← override wins
//   borderRadius: 12           ← new property added
// }

StyleSheet.hairlineWidth

StyleSheet.hairlineWidth returns the thinnest possible line width on the current device — typically 0.5 on retina displays and 1 on lower-density screens. Use it for thin dividers and borders that look crisp at any pixel density. It is preferable to hardcoding borderWidth: 0.5 because hairlineWidth adapts to the screen's pixel ratio automatically. This is a small but noticeable polish detail on high-density screens like modern iPhone and Pixel devices.

import { View, StyleSheet } from 'react-native';

// A 1-physical-pixel divider line
export default function Divider() {
  return <View style={styles.divider} />;
}

const styles = StyleSheet.create({
  divider: {
    height: StyleSheet.hairlineWidth,  // thinnest possible
    backgroundColor: '#e0e0e0',
    marginVertical: 8,
  },
});

// StyleSheet.hairlineWidth value:
// Retina (2× pixel ratio) → 0.5
// 3× pixel ratio → 0.333...
// 1× screen → 1

Colocating Styles with Components

A common convention is to define styles at the bottom of the same file as the component that uses them. This keeps related code together and makes it easy to understand a component's full visual specification without opening another file. For very large components with many style sections, you might split styles into a separate ComponentName.styles.ts file. Avoid creating a single global styles.js file for the whole app — it grows unmanageable and makes it hard to know which styles are used where.

// ProfileCard.tsx
import { View, Text, StyleSheet } from 'react-native';

export default function ProfileCard({ name, bio }) {
  return (
    <View style={styles.card}>
      <Text style={styles.name}>{name}</Text>
      <Text style={styles.bio}>{bio}</Text>
    </View>
  );
}

// Styles defined at the bottom of the same file
const styles = StyleSheet.create({
  card: { backgroundColor: '#fff', borderRadius: 16, padding: 20 },
  name: { fontSize: 20, fontWeight: 'bold', color: '#111' },
  bio: { fontSize: 14, color: '#555', marginTop: 6, lineHeight: 20 },
});

Dark Mode-Aware Styles

To support dark mode, use the useColorScheme hook to detect the current scheme ('light' or 'dark'), then select different color values for each mode. Combine this with your style array: the base styles hold layout and shape, while a dynamic color object applies theme-specific colors. A more scalable approach is a ThemeContext that provides color tokens throughout the app, but useColorScheme is the quickest way to get dark mode working without any extra libraries.

import { View, Text, StyleSheet, useColorScheme } from 'react-native';

export default function ThemedCard({ title }) {
  const scheme = useColorScheme(); // 'light' | 'dark'
  const colors = scheme === 'dark'
    ? { bg: '#1c1c1e', text: '#f0f0f0', border: '#3a3a3c' }
    : { bg: '#ffffff', text: '#111111', border: '#e0e0e0' };

  return (
    <View style={[styles.card, { backgroundColor: colors.bg, borderColor: colors.border }]}>
      <Text style={[styles.title, { color: colors.text }]}>{title}</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  card: { borderWidth: 1, borderRadius: 12, padding: 16, marginBottom: 12 },
  title: { fontSize: 18, fontWeight: '600' },
});

Styled Components in React Native

If you prefer a CSS-in-JS syntax, styled-components works with React Native. Install it with npm install styled-components and use the styled.View, styled.Text factories. Styled-components generate optimized StyleSheet entries under the hood while letting you write CSS-like syntax with template literals (use single quotes inside, not backticks with interpolation for static styles). It also supports props-based dynamic styling with full TypeScript support. Many teams prefer it for the familiar CSS authoring experience.

import styled from 'styled-components/native';

// Define styled components
const Card = styled.View`
  background-color: #fff;
  border-radius: 12px;
  padding: 16px;
  margin-bottom: 12px;
  elevation: 3;
`;

const Title = styled.Text`
  font-size: 18px;
  font-weight: bold;
  color: #222;
`;

export default function StyledCard({ title }) {
  return (
    <Card>
      <Title>{title}</Title>
    </Card>
  );
}

Quick Check

Test your understanding of React Native Mobile Development concepts from this lesson.

Lesson Recap

In this lesson you learned: StyleSheet.create is more efficient than inline objects because styles are sent as IDs not full objects, style arrays merge multiple style objects with later entries taking precedence, and useColorScheme enables dark mode-aware styling. Next up we explore Flexbox direction, justifyContent, and alignItems for full layout control.

الأسئلة الشائعة

هل درس «‏StyleSheet.create والأنماط المضمّنة» مجاني؟

نعم — نص درس «‏StyleSheet.create والأنماط المضمّنة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة React Native Academy، انتقل إلى CoddyKit PRO. تتضمن دورة React Native Academy 4 دروس في المجموع.

ماذا ستتعلم في «‏StyleSheet.create والأنماط المضمّنة»؟

أنشئ كائنات الأنماط باستخدام StyleSheet.create لتحسين الأداء، وقارنها بالأنماط المضمّنة، وطبّق عدة أنماط باستخدام المصفوفات. تتمرن على React Native Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ React Native Academy؟

لا تُشترط خبرة سابقة. React Native Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.

كم من الوقت يستغرق درس «‏StyleSheet.create والأنماط المضمّنة»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس React Native Academy هذا؟

نعم. كل درس في React Native Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. ‏StyleSheet.create والأنماط المضمّنة
  2. اتجاه Flexbox وJustifyContent وAlignItems
  3. ‏flex وflexGrow والتحجيم المتجاوب
  4. إنشاء شبكة بطاقات متجاوبة
← العودة إلى React Native Academy