diff a/modules/javafx.graphics/src/main/java/javafx/scene/text/TextFlow.java b/modules/javafx.graphics/src/main/java/javafx/scene/text/TextFlow.java
--- a/modules/javafx.graphics/src/main/java/javafx/scene/text/TextFlow.java
+++ b/modules/javafx.graphics/src/main/java/javafx/scene/text/TextFlow.java
@@ -51,11 +51,14 @@
 import com.sun.javafx.scene.text.GlyphList;
 import com.sun.javafx.scene.text.TextLayout;
 import com.sun.javafx.scene.text.TextLayoutFactory;
 import com.sun.javafx.scene.text.TextSpan;
 import com.sun.javafx.tk.Toolkit;
+import javafx.beans.property.IntegerProperty;
+import javafx.beans.property.IntegerPropertyBase;
 import javafx.css.Styleable;
+import javafx.css.StyleableIntegerProperty;
 import javafx.css.StyleableProperty;
 
 /**
  * TextFlow is special layout designed to lay out rich text.
  * It can be used to layout several {@link Text} nodes in a single text flow.
@@ -381,10 +384,11 @@
 
     TextLayout getTextLayout() {
         if (layout == null) {
             TextLayoutFactory factory = Toolkit.getToolkit().getTextLayoutFactory();
             layout = factory.createLayout();
+            layout.setTabSize(getTabSize());
             needsContent = true;
         }
         if (needsContent) {
             List<Node> children = getManagedChildren();
             TextSpan[] spans = new TextSpan[children.size()];
@@ -481,10 +485,59 @@
                 }
             };
         }
         return lineSpacing;
     }
+    /**
+     * The size of a tab stop in spaces.
+     *
+     * @return the {@code tabSize} property
+     *
+     * @defaultValue {@code 8}
+     *
+     * @since 14
+     */
+    private IntegerProperty tabSize;
+
+    /**
+     * Gets the size of a tab stop in spaces.
+     * @return the size of a tab in spaces
+     * @since 14
+     */
+    public final int getTabSize() {
+        return tabSize == null ? TextLayout.DEFAULT_TAB_SIZE : tabSize.get();
+    }
+
+    /**
+     * Sets the size of a tab stop.
+     * @param spaces the size of a tab in spaces. Defaults to 8.
+     * Minimum is 1, lower values will be clamped to 1.
+     * @since 14
+    */
+    public final void setTabSize(int spaces) {
+        tabSizeProperty().set(spaces);
+    }
+
+    final IntegerProperty tabSizeProperty() {
+        if (tabSize == null) {
+            tabSize = new StyleableIntegerProperty(TextLayout.DEFAULT_TAB_SIZE) {
+                @Override public Object getBean() { return TextFlow.this; }
+                @Override public String getName() { return "tabSize"; }
+                @Override public CssMetaData getCssMetaData() {
+                    return StyleableProperties.TAB_SIZE;
+                }
+                @Override public void set(int v) { super.set((v < 1) ? 1 : v); }
+                @Override protected void invalidated() {
+                    TextLayout layout = getTextLayout();
+                    if (layout.setTabSize(get())) {
+                        requestLayout();
+                    }
+                }
+            };
+        }
+        return tabSize;
+    }
 
     @Override public final double getBaselineOffset() {
         Insets insets = getInsets();
         double top = snapSpaceY(insets.getTop());
         return top - getTextLayout().getBounds().getMinY();
@@ -497,49 +550,65 @@
     **************************************************************************/
 
     /*
      * Super-lazy instantiation pattern from Bill Pugh.
      */
-     private static class StyleableProperties {
+    private static class StyleableProperties {
 
-         private static final
-             CssMetaData<TextFlow, TextAlignment> TEXT_ALIGNMENT =
-                 new CssMetaData<TextFlow,TextAlignment>("-fx-text-alignment",
-                 new EnumConverter<TextAlignment>(TextAlignment.class),
-                 TextAlignment.LEFT) {
+        private static final
+            CssMetaData<TextFlow, TextAlignment> TEXT_ALIGNMENT =
+                new CssMetaData<TextFlow,TextAlignment>("-fx-text-alignment",
+                new EnumConverter<TextAlignment>(TextAlignment.class),
+                TextAlignment.LEFT) {
 
             @Override public boolean isSettable(TextFlow node) {
                 return node.textAlignment == null || !node.textAlignment.isBound();
             }
 
             @Override public StyleableProperty<TextAlignment> getStyleableProperty(TextFlow node) {
                 return (StyleableProperty<TextAlignment>)node.textAlignmentProperty();
             }
-         };
+        };
 
-         private static final
-             CssMetaData<TextFlow,Number> LINE_SPACING =
-                 new CssMetaData<TextFlow,Number>("-fx-line-spacing",
-                 SizeConverter.getInstance(), 0) {
+        private static final
+            CssMetaData<TextFlow,Number> LINE_SPACING =
+                new CssMetaData<TextFlow,Number>("-fx-line-spacing",
+                SizeConverter.getInstance(), 0) {
 
             @Override public boolean isSettable(TextFlow node) {
                 return node.lineSpacing == null || !node.lineSpacing.isBound();
             }
 
             @Override public StyleableProperty<Number> getStyleableProperty(TextFlow node) {
                 return (StyleableProperty<Number>)node.lineSpacingProperty();
             }
-         };
+        };
+
+        private static final CssMetaData<TextFlow,Number> TAB_SIZE =
+                new CssMetaData<TextFlow,Number>("-fx-tab-size",
+                SizeConverter.getInstance(), TextLayout.DEFAULT_TAB_SIZE) {
+
+            @Override
+            public boolean isSettable(TextFlow node) {
+                return node.tabSize == null || !node.tabSize.isBound();
+            }
 
-     private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
-         static {
+            @Override
+            public StyleableProperty<Number> getStyleableProperty(TextFlow node) {
+                return (StyleableProperty<Number>)node.tabSizeProperty();
+            }
+        };
+
+        private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
+        static {
             final List<CssMetaData<? extends Styleable, ?>> styleables =
                 new ArrayList<CssMetaData<? extends Styleable, ?>>(Pane.getClassCssMetaData());
             styleables.add(TEXT_ALIGNMENT);
             styleables.add(LINE_SPACING);
+            styleables.add(TAB_SIZE);
             STYLEABLES = Collections.unmodifiableList(styleables);
-         }
+        }
     }
 
     /**
      * @return The CssMetaData associated with this class, which may include the
      * CssMetaData of its superclasses.
