Custom Typography Styles in Jetpack Compose: A Comprehensive Guide

Typography is a crucial aspect of user interface design. It defines how text looks and conveys information. In Jetpack Compose, customizing typography styles allows developers to create visually appealing and consistent UIs. This involves defining custom fonts, font weights, sizes, and other properties that match the app’s design system. In this guide, we’ll delve into creating custom typography styles in Jetpack Compose.

Understanding Typography in Jetpack Compose

In Jetpack Compose, typography is managed using the TextStyle class, which encapsulates various properties like font family, font weight, font size, line height, and letter spacing. Compose provides a default typography through the MaterialTheme.typography, but you can override this to apply your own custom styles.

Why Use Custom Typography Styles?

  • Consistency: Ensures that the text styles are consistent throughout the app.
  • Branding: Helps to reflect the brand identity by using specific fonts and styles.
  • Readability: Improves the readability and accessibility of the content.
  • Theme Support: Supports theming, allowing easy changes to the app’s visual appearance.

How to Implement Custom Typography Styles in Jetpack Compose

Implementing custom typography styles involves these key steps:

Step 1: Add Custom Fonts

To use custom fonts, add the font files (e.g., .ttf or .otf) to the res/font directory. If the directory doesn’t exist, create it under the res folder.

Font Folder Structure

Step 2: Define Font Family

Create a FontFamily using the Font composable, linking your font files to the appropriate font weights and styles.


import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.res.fontResource

val Cabin = FontFamily(
    Font(resId = R.font.cabin_regular, weight = FontWeight.Normal),
    Font(resId = R.font.cabin_bold, weight = FontWeight.Bold),
    Font(resId = R.font.cabin_italic, style = FontStyle.Italic),
    Font(resId = R.font.cabin_bolditalic, weight = FontWeight.Bold, style = FontStyle.Italic)
)

Step 3: Create Custom Typography

Define a Typography object and override the default styles to match your design system.


import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp

val CustomTypography = Typography(
    displayLarge = TextStyle(
        fontFamily = Cabin,
        fontWeight = FontWeight.Bold,
        fontSize = 57.sp,
        lineHeight = 64.sp,
        letterSpacing = (-0.25).sp
    ),
    displayMedium = TextStyle(
        fontFamily = Cabin,
        fontWeight = FontWeight.Bold,
        fontSize = 45.sp,
        lineHeight = 52.sp,
        letterSpacing = 0.sp
    ),
    displaySmall = TextStyle(
        fontFamily = Cabin,
        fontWeight = FontWeight.Bold,
        fontSize = 36.sp,
        lineHeight = 44.sp,
        letterSpacing = 0.sp
    ),
    headlineLarge = TextStyle(
        fontFamily = Cabin,
        fontWeight = FontWeight.Bold,
        fontSize = 32.sp,
        lineHeight = 40.sp,
        letterSpacing = 0.sp
    ),
    headlineMedium = TextStyle(
        fontFamily = Cabin,
        fontWeight = FontWeight.Bold,
        fontSize = 28.sp,
        lineHeight = 36.sp,
        letterSpacing = 0.sp
    ),
    headlineSmall = TextStyle(
        fontFamily = Cabin,
        fontWeight = FontWeight.Bold,
        fontSize = 24.sp,
        lineHeight = 32.sp,
        letterSpacing = 0.sp
    ),
    titleLarge = TextStyle(
        fontFamily = Cabin,
        fontWeight = FontWeight.Bold,
        fontSize = 22.sp,
        lineHeight = 28.sp,
        letterSpacing = 0.sp
    ),
    titleMedium = TextStyle(
        fontFamily = Cabin,
        fontWeight = FontWeight.Bold,
        fontSize = 16.sp,
        lineHeight = 24.sp,
        letterSpacing = 0.15.sp
    ),
    titleSmall = TextStyle(
        fontFamily = Cabin,
        fontWeight = FontWeight.Bold,
        fontSize = 14.sp,
        lineHeight = 20.sp,
        letterSpacing = 0.1.sp
    ),
    bodyLarge = TextStyle(
        fontFamily = Cabin,
        fontWeight = FontWeight.Normal,
        fontSize = 16.sp,
        lineHeight = 24.sp,
        letterSpacing = 0.15.sp
    ),
    bodyMedium = TextStyle(
        fontFamily = Cabin,
        fontWeight = FontWeight.Normal,
        fontSize = 14.sp,
        lineHeight = 20.sp,
        letterSpacing = 0.25.sp
    ),
    bodySmall = TextStyle(
        fontFamily = Cabin,
        fontWeight = FontWeight.Normal,
        fontSize = 12.sp,
        lineHeight = 16.sp,
        letterSpacing = 0.4.sp
    ),
    labelLarge = TextStyle(
        fontFamily = Cabin,
        fontWeight = FontWeight.Medium,
        fontSize = 14.sp,
        lineHeight = 20.sp,
        letterSpacing = 0.1.sp
    ),
    labelMedium = TextStyle(
        fontFamily = Cabin,
        fontWeight = FontWeight.Medium,
        fontSize = 12.sp,
        lineHeight = 16.sp,
        letterSpacing = 0.5.sp
    ),
    labelSmall = TextStyle(
        fontFamily = Cabin,
        fontWeight = FontWeight.Medium,
        fontSize = 11.sp,
        lineHeight = 16.sp,
        letterSpacing = 0.5.sp
    )
)

Step 4: Provide the Custom Typography in Your Theme

Pass your custom Typography to the MaterialTheme composable.


import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable

@Composable
fun AppTheme(content: @Composable () -> Unit) {
    MaterialTheme(
        typography = CustomTypography,
        content = content
    )
}

Step 5: Use Custom Typography in Your UI

Use the custom typography in your UI components.


import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview

@Composable
fun TextViewExample() {
    Text(
        text = "Hello, Compose!",
        style = MaterialTheme.typography.titleLarge
    )
}

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    AppTheme {
        TextViewExample()
    }
}

Additional Tips

  • Consider Accessibility: Ensure that your typography choices meet accessibility guidelines.
  • Use Consistent Naming: Follow a consistent naming convention for your typography styles.
  • Test on Different Devices: Test your typography styles on different screen sizes and resolutions.

Conclusion

Customizing typography styles in Jetpack Compose involves adding custom fonts, defining font families, creating custom typography objects, and providing them in your theme. By following these steps, you can ensure a consistent and visually appealing UI that reflects your brand’s identity and improves the overall user experience. Proper typography enhances readability and accessibility, making your app more engaging and user-friendly.