Skip to content

文本方向(dir 属性)

世界上并非所有语言都是从左到右书写的。阿拉伯语、希伯来语等语言使用从右到左(RTL)的书写方向,而中文、英文等使用从左到右(LTR)的方向。dir 属性和 CSS Logical Properties 使得开发者能够轻松构建支持双向文本的网页。本节将详细介绍 dir 属性的用法、RTL 适配策略,以及现代 CSS Logical Properties 的应用。

前置知识

阅读本节前,建议先了解:字符编码(UTF-8)

文本方向概述

LTR 与 RTL

方向英文缩写代表语言
从左到右LTR中文、英文、日文、韩文、法文、德文等
从右到左RTL阿拉伯语、希伯来语、波斯语、乌尔都语等
双向BiDi混合 LTR 和 RTL 的内容

dir 属性

基本用法

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>文本方向示例</title>
</head>
<body>
  <!-- LTR(默认) -->
  <p dir="ltr">这是从左到右的文本。</p>

  <!-- RTL -->
  <p dir="rtl">هذا نص من اليمين إلى اليسار.</p>

  <!-- 自动检测 -->
  <p dir="auto">Hello مرحبا 你好</p>
</body>
</html>

dir 属性值

说明适用场景
ltr从左到右默认值,大多数语言
rtl从右到左阿拉伯语、希伯来语等
auto浏览器自动检测混合内容(如用户输入)

文档级别方向

html
<!-- 中文网站(LTR) -->
<!DOCTYPE html>
<html lang="zh-CN" dir="ltr">
  <body>...</body>
</html>

<!-- 阿拉伯语网站(RTL) -->
<!DOCTYPE html>
<html lang="ar" dir="rtl">
  <body>...</body>
</html>

<!-- 希伯来语网站(RTL) -->
<!DOCTYPE html>
<html lang="he" dir="rtl">
  <body>...</body>
</html>

元素级别方向

html
<!-- 在 LTR 文档中嵌入 RTL 内容 -->
<p>他说:<span lang="ar" dir="rtl">مرحبا بالعالم</span></p>

<!-- 用户评论(自动检测方向) -->
<div class="comment" dir="auto">
  <!-- 如果用户输入的是阿拉伯语,自动显示为 RTL -->
  <!-- 如果用户输入的是中文,自动显示为 LTR -->
</div>

CSS Logical Properties

传统 CSS 属性使用物理方向(left/right/top/bottom),在 RTL 布局中需要反转。CSS Logical Properties 使用逻辑方向(inline/block),自动适应文本方向。

物理属性 vs 逻辑属性

传统物理属性CSS 逻辑属性LTR 中的效果RTL 中的效果
margin-leftmargin-inline-start左外边距右外边距
margin-rightmargin-inline-end右外边距左外边距
padding-leftpadding-inline-start左内边距右内边距
padding-rightpadding-inline-end右内边距左内边距
text-align: lefttext-align: start左对齐右对齐
text-align: righttext-align: end右对齐左对齐
leftinset-inline-start左定位右定位
rightinset-inline-end右定位左定位
border-leftborder-inline-start左边框右边框
float: leftfloat: inline-start左浮动右浮动

使用示例

html
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
  <meta charset="UTF-8">
  <title>CSS Logical Properties RTL 示例</title>
  <style>
    /* 传统方式:RTL 下需要覆盖 */
    /* 不推荐 */
    .box {
      margin-left: 2rem;
      padding-right: 1rem;
      border-left: 3px solid #0066cc;
      text-align: right;
      float: left;
    }

    [dir="rtl"] .box {
      margin-left: 0;
      margin-right: 2rem;
      padding-right: 0;
      padding-left: 1rem;
      border-left: none;
      border-right: 3px solid #0066cc;
      text-align: left;
      float: right;
    }

    /* 逻辑属性方式:自动适应 */
    /* 推荐 */
    .logical-box {
      margin-inline-start: 2rem;   /* LTR=左,RTL=右 */
      padding-inline-end: 1rem;     /* LTR=右,RTL=左 */
      border-inline-start: 3px solid #0066cc;
      text-align: start;           /* LTR=左,RTL=右 */
      float: inline-start;         /* LTR=左浮动,RTL=右浮动 */
    }
  </style>
</head>
<body>
  <div class="logical-box">
    <p>这段文字在 RTL 布局中自动适应方向。</p>
  </div>
</body>
</html>

逻辑尺寸属性

css
/* 物理 vs 逻辑 尺寸 */
.widthinline-size      /* 宽度 */
.heightblock-size       /* 高度 */
.min-widthmin-inline-size
.max-widthmax-inline-size
.min-heightmin-block-size
.max-heightmax-block-size

/* 逻辑位置 */
.topinset-block-start
.bottominset-block-end

/* 逻辑方向简写 */
.inset-inline: 1rem 2rem;   /* 上下+左右 逻辑方向 */
.inset-block: 1rem 2rem;

RTL 适配策略

镜像布局

RTL 网站通常是 LTR 网站的镜像:

LTR:  [Logo]  [Nav1] [Nav2] [Nav3]  [Search]
RTL:  [Search]  [Nav3] [Nav2] [Nav1]  [Logo]
html
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
  <meta charset="UTF-8">
  <title>RTL 适配示例</title>
  <style>
    /* 使用逻辑属性自动镜像 */
    .header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding-inline: 2rem;  /* LTR=左右,RTL=右左 */
    }

    .logo {
      margin-inline-end: auto;  /* LTR=右,RTL=左 */
    }

    .nav {
      display: flex;
      gap: 1.5rem;
      list-style: none;
    }

    .content {
      display: grid;
      grid-template-columns: 1fr 3fr;
      gap: 2rem;
    }

    /* 使用 start/end 而非 left/right */
    .sidebar {
      border-inline-start: 2px solid #e0e0e0;
      padding-inline-start: 1.5rem;
    }

    /* 文本对齐自动适应 */
    .text-start { text-align: start; }
    .text-end { text-align: end; }
  </style>
</head>
<body>
  <header class="header">
    <div class="logo">شركة</div>
    <nav>
      <ul class="nav">
        <li><a href="/">الرئيسية</a></li>
        <li><a href="/products">المنتجات</a></li>
        <li><a href="/about">من نحن</a></li>
      </ul>
    </nav>
  </header>

  <div class="content">
    <aside class="sidebar">
      <!-- 侧边栏自动移到右侧(RTL 中) -->
      <h2>القائمة الجانبية</h2>
      <ul>
        <li><a href="#">رابط 1</a></li>
        <li><a href="#">رابط 2</a></li>
      </ul>
    </aside>
    <main>
      <h1>مرحبا بك</h1>
      <p>هذا هو محتوى الصفحة الرئيسية.</p>
    </main>
  </div>
</body>
</html>

不需要镜像的元素

元素是否镜像原因
文字内容方向由 dir 属性控制
电话号码数字方向固定
URL网址方向固定
图标方向固定的图标不镜像
时间显示时间格式不变
箭头图标可能指向性箭头需要镜像

图标镜像

css
/* 需要镜像的图标 */
.arrow-icon {
  transform: scaleX(1); /* LTR */
}

[dir="rtl"] .arrow-icon {
  transform: scaleX(-1); /* RTL:水平翻转 */
}

/* 使用 CSS 逻辑属性实现 */
.arrow-icon {
  transform: scaleX(var(--direction, 1));
}

[dir="rtl"] {
  --direction: -1;
}

bdi 元素

<bdi>(Bidirectional Isolate)元素用于隔离双向文本,防止其影响周围的文本方向:

html
<!-- 用户名可能是任意语言 -->
<p>用户 <bdi>إبراهيم</bdi> 发布了 5 条评论。</p>
<!-- bdi 确保阿拉伯语用户名不影响周围中文文本的方向 -->

<!-- 不使用 bdi 的问题 -->
<p>用户 إبراهيم 发布了 5 条评论。</p>
<!-- 阿拉伯语用户名可能使 "5 条评论" 的方向被反转 -->

<!-- bdo 元素:强制覆盖文本方向 -->
<bdo dir="rtl">这段文字会被强制从右到左显示</bdo>

实战示例:双向支持页面

html
<!DOCTYPE html>
<html lang="zh-CN" dir="ltr">
<head>
  <meta charset="UTF-8">
  <title>双向文本支持页面</title>
  <style>
    /* 使用逻辑属性 */
    :root {
      --primary: #0066cc;
      --bg: #ffffff;
      --text: #1a1a2e;
      --border: #e0e0e0;
    }

    body {
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
      color: var(--text);
      background: var(--bg);
      padding-inline: 2rem;
      max-inline-size: 800px;
      margin-inline: auto;
    }

    .card {
      border: 1px solid var(--border);
      border-radius: 8px;
      padding: 1.5rem;
      margin-block: 1rem;
    }

    .comment {
      display: flex;
      gap: 1rem;
      margin-block: 1rem;
    }

    .avatar {
      width: 48px;
      height: 48px;
      border-radius: 50%;
      background: var(--primary);
      color: white;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .comment-content {
      flex: 1;
    }

    .comment-meta {
      font-size: 0.875rem;
      color: #666;
      margin-block-end: 0.5rem;
    }

    /* dir="auto" 自动检测方向 */
    .user-text {
      dir: auto;
    }
  </style>
</head>
<body>
  <h1>多语言评论</h1>

  <!-- 中文评论 -->
  <div class="comment">
    <div class="avatar">张</div>
    <div class="comment-content">
      <div class="comment-meta">张三 · 2024-01-15</div>
      <p class="user-text">这个教程写得太好了,收藏了!</p>
    </div>
  </div>

  <!-- 阿拉伯语评论 -->
  <div class="comment">
    <div class="avatar">إ</div>
    <div class="comment-content">
      <div class="comment-meta"><bdi>إبراهيم</bdi> · 2024-01-14</div>
      <p class="user-text">هذا الدرس ممتاز! شكرا لك.</p>
    </div>
  </div>

  <!-- 希伯来语评论 -->
  <div class="comment">
    <div class="avatar">י</div>
    <div class="comment-content">
      <div class="comment-meta"><bdi>יעל</bdi> · 2024-01-13</div>
      <p class="user-text">מדריך מעולה! תודה רבה.</p>
    </div>
  </div>

  <!-- 混合内容 -->
  <div class="card">
    <h2>混合方向文本</h2>
    <p>
      在中文中引用英文:<span lang="en" dir="ltr">Hello World</span>,以及阿拉伯语:
      <span lang="ar" dir="rtl">مرحبا</span>。
    </p>
  </div>
</body>
</html>

注意事项

  1. dir 属性影响整个子树:在元素上设置 dir 会影响所有子元素
  2. 混合语言使用 bdi:防止双向文本影响周围内容
  3. CSS 逻辑属性不改变方向:只是让属性值自适应 dir 方向
  4. 测试 RTL 布局:确保镜像后布局正确
  5. 图标注意方向:方向性图标(箭头等)需要在 RTL 中翻转

最佳实践

  • 使用 CSS Logical Properties 替代物理方向属性
  • <html> 标签上正确设置 dir 属性
  • 混合语言内容使用 dir="auto"<bdi> 元素
  • 测试 LTR 和 RTL 两种布局
  • 镜像布局时注意图标方向
  • 使用 [dir="rtl"] 选择器处理特殊 RTL 样式

下一节

继续学习:多语言页面设计

参考链接