ParagraphStyle — Concepts clés, propriétés et utilisation

Auteur : IT Sectr Publié le : 2026-07-25 Temps de lecture : 10 min

ParagraphStyle est un ensemble de paramètres de formatage qui définissent l'apparence visuelle d'un paragraphe de texte. Dans le développement mobile, ParagraphStyle inclut l'alignement (left, center, right, justified), l'interlignage, le retrait de première ligne, l'espacement entre les paragraphes et la direction du texte. D'après les Material Design Typography Guidelines (2025), une utilisation cohérente de ParagraphStyle sur tous les écrans de l'application garantit un rythme typographique uniforme et réduit le bruit visuel lors du passage d'une section à l'autre.

Points essentiels

  • ParagraphStyle — objet de paramètres de formatage de paragraphe : alignement, retrait, espacement.
  • Plateformes — iOS : NSMutableParagraphStyle, Android : ParagraphStyle (Compose) / Layout (View), Flutter : TextStyle.
  • Alignement — left pour le texte principal, center pour les titres, justified pour le format livre.
  • Retrait — firstLineHeadIndent (retrait de première ligne), paragraphSpacing (espacement entre paragraphes).
  • Localisation — ParagraphStyle tient compte de la direction du texte (LTR/RTL) pour différentes langues.

Qu'est-ce que ParagraphStyle en typographie

ParagraphStyle (style de paragraphe) est un ensemble de règles de formatage applicables à un ou plusieurs paragraphes de texte. Contrairement aux styles de caractère (bold, italic, font-size) qui agissent au niveau des caractères individuels, ParagraphStyle gère les macro-propriétés : le placement du texte dans le conteneur, les espacements entre lignes et paragraphes, la direction d'écriture et les règles de césure.

Historiquement, le concept de ParagraphStyle provient des systèmes de publication assistée par ordinateur (QuarkXPress, PageMaker, InDesign), où chaque paragraphe avait son propre ensemble de paramètres. Dans le développement mobile, cette approche s'est transformée en API logicielles : NSMutableParagraphStyle sur iOS, les classes ParagraphStyle et LineBreakStyle sous Android, et des paramètres comme textAlign et textHeightBehavior dans Flutter. Tous servent un même objectif — gérer le formatage des paragraphes via le code, sans être lié à un moteur de texte spécifique.

D'après Bringhurst — The Elements of Typographic Style (2024), une configuration correcte de ParagraphStyle est le fondement de la culture typographique d'une interface. Si la police et la taille de caractère définissent la « voix » du texte, le style de paragraphe définit sa « respiration » : rythme, pauses et accents. Dans les interfaces mobiles où l'espace est limité, un ParagraphStyle approprié permet d'inclure plus d'informations sans perte de lisibilité.

Propriétés principales de ParagraphStyle

ParagraphStyle comprend plusieurs groupes de propriétés, chacun responsable d'un aspect spécifique du formatage. Examinons les paramètres clés disponibles dans les API mobiles. L'alignement est le paramètre principal qui détermine la position horizontale du texte. Sur iOS, NSTextAlignment est disponible, sur Android — Layout.Alignment, dans Flutter — TextAlign.

PropriétéiOS (NSMutableParagraphStyle)Android (Compose)Flutter (TextStyle)
AlignementalignmenttextAligntextAlign
Retrait gaucheheadIndenttextIndent (dans Compose)
Retrait droittailIndent
Retrait de première lignefirstLineHeadIndenttextIndent (firstLine)
Espacement entre paragraphesparagraphSpacingparagraphStyle (lineHeight)
Espacement avant paragrapheparagraphSpacingBefore
Direction du textebaseWritingDirectionTextDirection (Compose)textDirection
Mode de saut de lignelineBreakModeoverflow (TextStyle)overflow (TextStyle)

Il est important de comprendre que toutes les propriétés ne sont pas disponibles sur toutes les plateformes dans la même mesure. Par exemple, le retrait de première ligne (firstLineHeadIndent) n'est entièrement pris en charge que sur iOS via NSMutableParagraphStyle. Sous Android, on utilise SpannableString avec LeadingMarginSpan à cette fin, et dans Flutter — RichText avec TextSpan personnalisé et padding. Dans le développement multiplateforme (Flutter, React Native), certaines propriétés de ParagraphStyle doivent être émulées via des conteneurs ou Spacer.

ParagraphStyle sous iOS : NSMutableParagraphStyle

Sous iOS, l'outil principal pour travailler avec le style de paragraphe est la classe NSMutableParagraphStyle — une sous-classe de NSParagraphStyle. Elle fournit un ensemble complet de propriétés pour gérer le formatage des paragraphes et est appliquée via NSAttributedString. NSMutableParagraphStyle est utilisé non seulement dans UILabel et UITextView, mais aussi dans Core Text via CTParagraphStyle.

swift
// iOS : configuration complète de ParagraphStyle
let paragraphStyle = NSMutableParagraphStyle()

// Alignement
paragraphStyle.alignment = .justified     // justifié

// Retrait
paragraphStyle.headIndent = 16          // retrait gauche
paragraphStyle.tailIndent = -16         // retrait droit (négatif)
paragraphStyle.firstLineHeadIndent = 32 // retrait de première ligne

// Espacement entre paragraphes
paragraphStyle.paragraphSpacing = 12    // après le paragraphe
paragraphStyle.paragraphSpacingBefore = 8 // avant le paragraphe

// Hauteur de ligne
paragraphStyle.minimumLineHeight = 24
paragraphStyle.maximumLineHeight = 24

let attributes: [NSAttributedString.Key: Any] = [
    .font: UIFont.systemFont(ofSize: 16),
    .paragraphStyle: paragraphStyle
]

let label = UILabel()
label.attributedText = NSAttributedString(
    string: "This paragraph has a custom ParagraphStyle.\n\nSecond paragraph with 12 pt spacing.",
    attributes: attributes
)

Dans SwiftUI, il n'existe pas d'équivalent direct de NSMutableParagraphStyle — à la place, une combinaison de modificateurs est utilisée : .multilineTextAlignment() pour l'alignement, .lineSpacing() pour l'interlignage. Pour le retrait de première ligne et l'espacement entre paragraphes dans SwiftUI, il faut utiliser Text + padding ou AttributedString (disponible depuis iOS 15+), qui prend en charge NSParagraphStyle via des attributs.

swift
// SwiftUI : AttributedString avec ParagraphStyle (iOS 15+)
var attributed: AttributedString = """
This is the first paragraph with indent.

This is the second paragraph with 12 pt spacing.
"""

let ps = NSMutableParagraphStyle()
ps.paragraphSpacing = 12
ps.firstLineHeadIndent = 20

let container = AttributeContainer()
    .paragraphStyle(ps)

attributed.mergeAttributes(container)

Text(attributed)
    .font(.body)

D'après Apple — Text Programming Guide (2025), NSMutableParagraphStyle prend en charge jusqu'à 14 paramètres de formatage différents. Il est important de se rappeler que tailIndent est défini comme une valeur négative par rapport à la largeur du conteneur, tandis que headIndent est positif. Ce comportement non évident cause souvent des erreurs chez les développeurs iOS débutants.

ParagraphStyle sous Android : système View et Compose

Sous Android, l'approche de ParagraphStyle diffère entre le système View et Jetpack Compose. Dans le système View classique, les paramètres de paragraphe sont définis via des attributs XML de TextView (android:textAlignment, android:lineSpacingExtra) ou via SpannableString avec des implémentations de l'interface ParagraphStyle du paquetage android.text.style.

kotlin
// Système Android View : ParagraphStyle via SpannableString
val text = "First paragraph with settings.\n\nSecond paragraph."
val spannable = SpannableString(text)

// Alignement justifié
spannable.setSpan(
    AlignmentSpan.Standard(Layout.Alignment.ALIGN_NORMAL),
    0, text.length,
    Spannable.SPAN_PARAGRAPH
)

// Retrait de première ligne via LeadingMarginSpan
spannable.setSpan(
    LeadingMarginSpan.Standard(0, 20),
    0, text.indexOf('\n'),
    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)

textView.text = spannable

Dans Jetpack Compose, ParagraphStyle est géré via les paramètres de TextStyle. textAlign est utilisé pour l'alignement, lineHeight (en sp ou em) pour l'interlignage, et textIndent pour le retrait de première ligne. Compose prend également en charge LineBreak pour un contrôle précis des sauts de ligne (Simple, Heading, Paragraph), ce qui est particulièrement utile pour le texte multilingue.

kotlin
// Jetpack Compose : ParagraphStyle via TextStyle
Text(
    text = "Premier paragraphe avec style personnalisé.

Deuxième paragraphe avec retrait.",
    style = TextStyle(
        textAlign = TextAlign.Justify,
        lineHeight = 24.sp,
        textIndent = TextIndent(firstLine = 16.sp),
        lineBreak = LineBreak.Paragraph
    )
)

D'après Android Developers — Compose ParagraphStyle (2025), lors de l'utilisation de TextIndent dans Compose, il est important de définir firstLine en sp (pas en dp), car le retrait de première ligne doit s'adapter à la taille du texte. Si le retrait est défini en dp, lorsque la taille de la police augmente, le retrait de première ligne deviendra visuellement plus petit, ce qui brisera les proportions typographiques.

ParagraphStyle sous Flutter : TextHeightBehavior et StrutStyle

Dans Flutter, le paradigme ParagraphStyle n'est pas séparé dans une classe dédiée — à la place, une combinaison de paramètres TextStyle et de classes supplémentaires est utilisée. L'alignement est défini via TextAlign, l'interlignage via height (sans unité), et TextHeightBehavior contrôle les retraits visibles de la première et de la dernière ligne.

dart
// Flutter : ParagraphStyle via les paramètres Text
Text(
    'Paragraphe stylisé dans Flutter.

Deuxième paragraphe avec retraits.',
    style: TextStyle(
        fontSize: 16,
        height: 1.5,
        leadingDistribution: TextLeadingDistribution.proportional,
    ),
    textAlign: TextAlign.justify,
    textHeightBehavior: TextHeightBehavior(
        applyHeightToFirstAscent: true,
        applyHeightToLastDescent: true,
    ),
)

Pour des scénarios plus complexes, Flutter propose l'utilisation de RichText avec TextSpan et WidgetSpan personnalisés. Cela permet de combiner du texte avec des widgets en ligne (icônes, images) dans un seul paragraphe, tout en maintenant des règles de formatage uniformes. Cependant, cette approche nécessite un contrôle manuel des sauts de ligne et ne prend pas en charge la césure automatique.

dart
// Flutter : RichText avec formatage de paragraphe personnalisé
RichText(
    text: TextSpan(
        style: TextStyle(fontSize: 16, height: 1.5),
        children: [
            TextSpan(text: 'First paragraph with icon '),
            WidgetSpan(
                child: Icon(Icons.star, size: 16),
                alignment: PlaceholderAlignment.middle,
            ),
            TextSpan(text: '\n\nSecond paragraph after spacing.'),
        ],
    ),
)

D'après Flutter Documentation — Text Widget (2025), TextHeightBehavior est un paramètre clé pour l'affichage correct de ParagraphStyle dans Flutter. Si applyHeightToFirstAscent est défini sur false, le retrait supérieur de la première ligne est ignoré et le texte « colle » à la bordure supérieure du conteneur. Ceci est utile pour les titres, mais indésirable pour le texte principal.

ParagraphStyle et localisation : LTR/RTL et particularités régionales

ParagraphStyle doit tenir compte de la direction d'écriture pour chaque locale. Dans les applications mobiles prenant en charge l'arabe, l'hébreu ou l'ourdou (écriture de droite à gauche, RTL), les retraits et l'alignement doivent être inversés. iOS prend en charge le basculement automatique via baseWritingDirection = .natural, Android via TextDirection, Flutter via textDirection.

La configuration de l'alignement pour les locales RTL nécessite une attention particulière. Si en mode LTR headIndent définit le retrait gauche, en RTL il devient automatiquement le retrait droit. Cependant, toutes les implémentations ne gèrent pas correctement cette transition lorsque l'alignement est spécifié explicitement (NSTextAlignment.left au lieu de NSTextAlignment.natural). D'après Google Internationalization Guide (2025), pour les applications multilingues, utilisez toujours l'alignement naturel et vérifiez les retraits dans les deux dispositions.

kotlin
// Android : prise en charge RTL dans ParagraphStyle
val textView = TextView(context)

// Activer la prise en charge RTL automatique
textView.textDirection = View.TEXT_DIRECTION_LOCALE
textView.textAlignment = View.TEXT_ALIGNMENT_TEXT_START

// Spannable avec prise en charge RTL
val spannable = SpannableString(arabicText)
spannable.setSpan(
    AlignmentSpan.Standard(Layout.Alignment.ALIGN_NORMAL),
    0, arabicText.length,
    Spannable.SPAN_PARAGRAPH
)

Les particularités régionales incluent également des règles différentes pour le retrait de première ligne. Dans la typographie européenne, le retrait de première ligne (firstLineHeadIndent) est une norme pour la séparation des paragraphes. Dans la typographie japonaise et chinoise, le retrait de première ligne est également utilisé, mais sa taille peut différer (généralement 1 em contre 1,5 em dans la tradition européenne). Pour la typographie arabe, le retrait de première ligne est rare — les paragraphes sont plus souvent séparés par un espacement vertical.

Erreurs courantes lors du travail avec ParagraphStyle

L'erreur la plus courante est d'utiliser ParagraphStyle uniquement via des attributs globaux du champ de texte sans tenir compte du formatage différent des paragraphes individuels. Dans un UILabel ou TextView avec plusieurs paragraphes séparés par , ParagraphStyle est appliqué uniformément à tout le texte, à moins d'utiliser du texte attribué avec des styles différents pour chaque paragraphe.

  • Ignorer paragraphSpacingBefore — de nombreux développeurs définissent paragraphSpacing mais oublient paragraphSpacingBefore. Pour le premier paragraphe d'un bloc, paragraphSpacingBefore permet de définir une marge supérieure sans créer de conteneur supplémentaire. Ceci est particulièrement utile pour les listes avec titres.
  • Alignement fixe (left/right) au lieu de natural — si l'application prend en charge les locales RTL, utiliser NSTextAlignment.left ou TextAlign.Start au lieu de natural entraîne un affichage incorrect dans les locales arabe et hébraïque.
  • Absence de vérification du mode de saut de ligne — dans les conteneurs étroits (listes, barres latérales), un lineBreakMode incorrect conduit à la troncature des mots. Utilisez byWordWrapping et vérifiez les mots longs dans le contexte de la locale spécifique.
  • Mélange de Spannable avec différents ParagraphStyle — lors de la configuration de Spannable avec SPAN_PARAGRAPH, il est important de calculer correctement les limites des paragraphes. Une discordance des positions de début/fin avec les limites réelles du paragraphe entraîne l'ignorance du style.
  • Alignement de ligne de base oublié — lors de l'utilisation de ParagraphStyle avec un lineHeight fixe (minimumLineHeight), assurez-vous que l'alignement du texte sur la ligne de base est activé. Sous iOS, label.baselineAdjustment = .alignBaselines est utilisé.

D'après UX Collective — Common Typography Bugs in Mobile Apps (2025), les problèmes avec ParagraphStyle représentent 18 % de tous les bugs typographiques dans les applications mobiles. Les cas les plus critiques sont lorsqu'un paragraphSpacing incorrect entraîne un chevauchement du texte sur différentes lignes ou lorsque les locales RTL s'affichent avec des retraits LTR. Il est recommandé de créer des tests unitaires pour chaque paramètre de ParagraphStyle avec des chaînes de test dans différentes langues.

Questions fréquentes

En quoi ParagraphStyle diffère-t-il de TextStyle sous iOS ?

NSMutableParagraphStyle gère le formatage des paragraphes (alignement, retrait, interlignage), tandis que TextStyle gère les attributs de caractère (police, couleur, taille). Les deux sont appliqués via NSAttributedString. ParagraphStyle agit au niveau du paragraphe, TextStyle au niveau des caractères. Plusieurs instances de TextStyle peuvent exister dans un paragraphe, mais un seul ParagraphStyle par paragraphe.

Comment définir un retrait de première ligne dans Jetpack Compose ?

Dans Jetpack Compose, le retrait de première ligne est défini via TextIndent à l'intérieur de TextStyle : TextStyle(textIndent = TextIndent(firstLine = 16.sp)). La valeur doit être en sp pour qu'elle s'adapte à la taille du texte. Pour le texte multiligne, le retrait s'applique à chaque ligne qui commence un nouveau paragraphe (caractère ). Pour le premier paragraphe, le retrait est toujours appliqué.

Comment configurer l'espacement entre paragraphes dans SwiftUI ?

Dans SwiftUI, il n'existe pas d'équivalent direct de paragraphSpacing. Pour l'espacement entre paragraphes, utilisez AttributedString (iOS 15+) avec NSMutableParagraphStyle et la propriété paragraphSpacing. Ou séparez les paragraphes via Text("...\n\n...") et ajoutez .padding() entre les blocs de texte. Pour les scénarios typographiques complexes, utilisez NSAttributedString via UILabelRepresentable.

Pourquoi paragraphSpacing ne fonctionne-t-il pas dans Android TextView ?

TextView sous Android n'a pas de propriété paragraphSpacing — elle est définie via SpannableString avec LeadingMarginSpan ou via un LineBackgroundSpan personnalisé. Pour l'interlignage, utilisez setLineSpacing ; pour l'espacement entre paragraphes, séparez les paragraphes avec un supplémentaire ou utilisez un conteneur composite de plusieurs instances TextView.

Comment ParagraphStyle affecte-t-il l'accessibilité des applications mobiles ?

Un ParagraphStyle approprié améliore l'accessibilité : un paragraphSpacing suffisant aide les utilisateurs ayant des troubles cognitifs à mieux distinguer les limites des paragraphes. WCAG 2.2 recommande la séparation visuelle des paragraphes (retrait ou espacement). ParagraphSpacing ne doit pas être inférieur à 1,5 × line-height. Pour les locales RTL, vérifiez que le retrait est correctement inversé.

Résumé

  • ParagraphStyle — ensemble de règles de formatage de paragraphe : alignement, retrait, interlignage et espacement entre paragraphes.
  • iOS — NSMutableParagraphStyle avec 14+ paramètres, appliqué via NSAttributedString ; dans SwiftUI — AttributedString (iOS 15+).
  • Android View — SpannableString avec des implémentations de ParagraphStyle (AlignmentSpan, LeadingMarginSpan).
  • Android Compose — TextStyle.textAlign, lineHeight, textIndent et LineBreak pour le contrôle des sauts de ligne.
  • Flutter — combinaison de TextStyle.height, TextAlign, TextHeightBehavior et StrutStyle pour fixer la hauteur de ligne.
  • Localisation — utilisez l'alignement naturel pour la prise en charge des locales RTL ; vérifiez les retraits dans les deux dispositions.
  • Erreurs courantes — alignement fixe au lieu de naturel, négligence de paragraphSpacingBefore, lineBreakMode incorrect pour les conteneurs étroits.

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi