Last modified: Jul 08, 2026

Python-docx Custom Styles Guide

Writing Word documents with Python is powerful. But repeating font sizes, colors, and spacing in every script is inefficient. You need a better way.

Custom styles in python-docx solve this problem. They let you define formatting once and reuse it everywhere. This saves time and ensures consistency across all your documents.

This guide shows you how to create, save, and reuse custom style templates. You will learn practical techniques for professional document generation.

Why Use Custom Styles?

Imagine generating 100 reports. Without styles, you must set font, size, bold, and color for each heading and paragraph individually. One mistake breaks the entire look.

Custom styles act like a blueprint. Define a style named "ReportTitle" once. Apply it to every title in your document. If you need to change the color later, update the style definition. Every title updates automatically.

This approach also makes your code cleaner and easier to maintain. Instead of long formatting chains, you use simple style names.

Understanding python-docx Style Objects

In python-docx, a style is an object attached to a document. Styles have a name, type, and formatting properties.

The most common style types are:

  • Paragraph styles – for paragraphs, headings, and body text.
  • Character styles – for inline text formatting like bold or italic.
  • Table styles – for table formatting.

Every new document comes with built-in styles like 'Normal', 'Heading 1', and 'List Bullet'. You can modify these or create new ones.

Creating a Custom Paragraph Style

Let's create a custom style called "CustomBody". We will set its font, size, color, and paragraph spacing.


from docx import Document
from docx.shared import Pt, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH

# Create a new document
doc = Document()

# Access the styles collection
styles = doc.styles

# Create a new paragraph style named 'CustomBody'
style = styles.add_style('CustomBody', 1)  # 1 = paragraph style

# Set font properties
style.font.name = 'Calibri'
style.font.size = Pt(11)
style.font.color.rgb = RGBColor(0x33, 0x33, 0x33)  # Dark gray

# Set paragraph properties
style.paragraph_format.space_after = Pt(6)
style.paragraph_format.line_spacing = 1.15

# Apply the style to a paragraph
doc.add_paragraph('This is custom body text.', style='CustomBody')
doc.add_paragraph('Another paragraph with the same style.', style='CustomBody')

doc.save('custom_style_example.docx')
print("Document saved with custom style.")

Document saved with custom style.

The style type argument (1 for paragraph, 2 for character) is important. Use the correct type for your needs.

Creating a Reusable Style Template

To reuse styles across multiple documents, save a document with your custom styles as a template. Then, load that template each time you generate a new document.


from docx import Document
from docx.shared import Pt, RGBColor, Inches

# Create a template document with custom styles
template = Document()

# Define a heading style
style_heading = template.styles.add_style('CustomHeading', 1)
style_heading.font.name = 'Arial'
style_heading.font.size = Pt(18)
style_heading.font.color.rgb = RGBColor(0x00, 0x56, 0x9B)  # Blue
style_heading.font.bold = True
style_heading.paragraph_format.space_before = Pt(12)
style_heading.paragraph_format.space_after = Pt(6)

# Define a body style
style_body = template.styles.add_style('CustomBody', 1)
style_body.font.name = 'Calibri'
style_body.font.size = Pt(11)
style_body.font.color.rgb = RGBColor(0x33, 0x33, 0x33)
style_body.paragraph_format.line_spacing = 1.15
style_body.paragraph_format.space_after = Pt(6)

# Add a dummy paragraph to force style inclusion
template.add_paragraph('', style='CustomHeading')
template.add_paragraph('', style='CustomBody')

# Save as template (.dotx)
template.save('my_styles_template.dotx')
print("Template saved as my_styles_template.dotx")

Template saved as my_styles_template.dotx

Now, when you create a new document, load the template instead of a blank document.


from docx import Document

# Load the template
doc = Document('my_styles_template.dotx')

# Use custom styles
doc.add_paragraph('Welcome to our report!', style='CustomHeading')
doc.add_paragraph('This is the first paragraph using the custom body style.', style='CustomBody')
doc.add_paragraph('Consistent formatting across all documents.', style='CustomBody')

doc.save('generated_report.docx')
print("Report generated with template styles.")

Report generated with template styles.

This method is the foundation of reusable style templates. For more advanced template techniques, see our guide on Python DOCX Templates with Jinja2.

Modifying Built-in Styles

Sometimes you don't need a new style. You can modify an existing built-in style like 'Normal' or 'Heading 1'. This is useful for global formatting changes.


from docx import Document
from docx.shared import Pt, RGBColor

doc = Document()

# Access the built-in 'Normal' style
normal_style = doc.styles['Normal']

# Modify its properties
normal_style.font.name = 'Times New Roman'
normal_style.font.size = Pt(12)
normal_style.font.color.rgb = RGBColor(0x00, 0x00, 0x00)  # Black
normal_style.paragraph_format.line_spacing = 1.5

# Now all paragraphs using 'Normal' will have these settings
doc.add_paragraph('This text uses the modified Normal style.')
doc.add_paragraph('Every paragraph inherits the new formatting.')

doc.save('modified_builtin_style.docx')
print("Document with modified built-in style saved.")

Document with modified built-in style saved.

Be careful when modifying built-in styles. Changes affect all text using that style in the document.

Character Styles for Inline Formatting

Character styles are perfect for highlighting words or phrases without affecting the entire paragraph. Create a style for emphasis, code snippets, or warnings.


from docx import Document
from docx.shared import Pt, RGBColor
from docx.enum.text import WD_BREAK

doc = Document()

# Create a character style (type 2)
emphasis_style = doc.styles.add_style('Emphasis', 2)
emphasis_style.font.name = 'Calibri'
emphasis_style.font.size = Pt(11)
emphasis_style.font.bold = True
emphasis_style.font.color.rgb = RGBColor(0xCC, 0x00, 0x00)  # Red

# Apply character style to a run within a paragraph
paragraph = doc.add_paragraph('This is ')
run = paragraph.add_run('very important')
run.style = doc.styles['Emphasis']
paragraph.add_run(' information.')

doc.save('character_style_example.docx')
print("Character style example saved.")

Character style example saved.

Use character styles for inline formatting that should be reusable across different paragraphs.

Best Practices for Style Templates

Following best practices ensures your style templates are robust and maintainable. For a deeper dive, check out Python docx Best Practices for Clean Generation.

  • Use descriptive names – Name styles like 'ReportTitle', 'SectionHeader', 'CodeBlock'. Avoid generic names like 'Style1'.
  • Keep styles in a separate template file – Do not redefine styles in every script. Load the template.
  • Test on a sample document – Verify your styles render correctly before using them in production.
  • Avoid over-nesting – Base styles on 'Normal' or 'Heading 1' instead of creating deep style hierarchies.

Sharing Style Templates Across Teams

Store your template file (.dotx) in a shared location like a version control repository or a network drive. Every team member loads the same template, ensuring brand consistency.

When you update the template, all new documents automatically use the latest styles. This is much easier than updating formatting in every script manually.

For advanced formatting needs like numbered headings, see our Python docx Numbered Headings Guide.

Conclusion

Custom styles in python-docx transform how you generate Word documents. They eliminate repetitive formatting code and guarantee consistency across all your outputs.

Start by creating a simple template with your most used styles. Save it as a .dotx file. Load it in every script that generates documents. This small investment pays off quickly in cleaner code and fewer formatting errors.

Remember to modify built-in styles carefully and use character styles for inline formatting. With these techniques, you can produce professional, branded documents at scale.

Now you have the tools to build reusable style templates. Apply them to your next automation project and experience the difference.