diff --git a/components/style/matching.rs b/components/style/matching.rs
index 15407d10eca..84189fde404 100644
--- a/components/style/matching.rs
+++ b/components/style/matching.rs
@@ -662,13 +662,9 @@ pub trait MatchMethods : TNode {
 
         let damage;
         if self.is_text_node() {
-            // Text nodes get a copy of the parent style. This ensures
-            // that during fragment construction any non-inherited
-            // CSS properties (such as vertical-align) are correctly
-            // set on the fragment(s).
             let mut data_ref = self.mutate_data().unwrap();
             let mut data = &mut *data_ref;
-            let cloned_parent_style = parent_style.unwrap().clone();
+            let cloned_parent_style = Self::ConcreteComputedValues::style_for_child_text_node(parent_style.unwrap());
             damage = Self::ConcreteRestyleDamage::compute(data.style.as_ref(),
                                                           &*cloned_parent_style);
             data.style = Some(cloned_parent_style);
diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs
index c49e210567b..1717f9ae1b7 100644
--- a/components/style/properties/properties.mako.rs
+++ b/components/style/properties/properties.mako.rs
@@ -1496,6 +1496,8 @@ pub trait ComputedValues : Clone + Send + Sync + 'static {
         % endfor
         ) -> Self;
 
+        fn style_for_child_text_node(parent: &Arc<Self>) -> Arc<Self>;
+
         fn initial_values() -> &'static Self;
 
         fn do_cascade_property<F: FnOnce(&Vec<Option<CascadePropertyFn<Self>>>)>(f: F);
@@ -1554,6 +1556,18 @@ impl ComputedValues for ServoComputedValues {
             }
         }
 
+        fn style_for_child_text_node(parent: &Arc<Self>) -> Arc<Self> {
+            // Text nodes get a copy of the parent style. Inheriting all non-
+            // inherited properties into the text node is odd from a CSS
+            // perspective, but makes fragment construction easier (by making
+            // properties like vertical-align on fragments have values that
+            // match the parent element). This is an implementation detail of
+            // Servo layout that is not central to how fragment construction
+            // works, but would be difficult to change. (Text node style is
+            // also not visible to script.)
+            parent.clone()
+        }
+
         fn initial_values() -> &'static Self { &*INITIAL_SERVO_VALUES }
 
         fn do_cascade_property<F: FnOnce(&Vec<Option<CascadePropertyFn<Self>>>)>(f: F) {
diff --git a/ports/geckolib/properties.mako.rs b/ports/geckolib/properties.mako.rs
index 8bfe9cba5f6..3804f3a25a9 100644
--- a/ports/geckolib/properties.mako.rs
+++ b/ports/geckolib/properties.mako.rs
@@ -69,6 +69,25 @@ impl ComputedValues for GeckoComputedValues {
         }
     }
 
+    fn style_for_child_text_node(parent: &Arc<Self>) -> Arc<Self> {
+        // Gecko expects text nodes to be styled as if they were elements that
+        // matched no rules (that is, inherited style structs are inherited and
+        // non-inherited style structs are set to their initial values).
+        Arc::new(GeckoComputedValues {
+            custom_properties: parent.custom_properties.clone(),
+            shareable: parent.shareable,
+            writing_mode: parent.writing_mode,
+            root_font_size: parent.root_font_size,
+            % for style_struct in data.style_structs:
+            % if style_struct.inherited:
+            ${style_struct.ident}: parent.${style_struct.ident}.clone(),
+            % else:
+            ${style_struct.ident}: Self::initial_values().${style_struct.ident}.clone(),
+            % endif
+            % endfor
+        })
+    }
+
     fn initial_values() -> &'static Self { &*INITIAL_GECKO_VALUES }
 
     fn do_cascade_property<F: FnOnce(&Vec<Option<CascadePropertyFn<Self>>>)>(f: F) {