servo: Merge #14089 - Make use of Servo-specific ToCss everywhere! (from Wafflespeanut:tocss); r=SimonSapin
authorRavi Shankar <wafflespeanut@gmail.com>
Sun, 06 Nov 2016 23:26:08 -0600
changeset 340081 82c014e4573ddb35efe074b6e4a9a0b1cc6bf6d4
parent 340080 77290a21f02ad2afb153cb808ce2ec39ebf0b563
child 340082 977d4aab5053926f2ae5aa0b5fb5e3f5f4427ff0
push id31307
push usergszorc@mozilla.com
push dateSat, 04 Feb 2017 00:59:06 +0000
treeherdermozilla-central@94079d43835f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersSimonSapin
servo: Merge #14089 - Make use of Servo-specific ToCss everywhere! (from Wafflespeanut:tocss); r=SimonSapin <!-- Please describe your changes on the following line: --> This will allow types to be generic over our local `ToCss` --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [ ] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors <!-- Either: --> - [x] These changes do not require tests because it's a refactor <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: f48b3fe2197a59b29bc711fb1b5496cbb97bd330
servo/components/layout/query.rs
servo/components/script/dom/cssstyledeclaration.rs
servo/components/script/dom/mediaquerylist.rs
servo/components/servo/Cargo.lock
servo/components/style/custom_properties.rs
servo/components/style/lib.rs
servo/components/style/media_queries.rs
servo/components/style/properties/declaration_block.rs
servo/components/style/properties/helpers.mako.rs
servo/components/style/properties/helpers/animated_properties.mako.rs
servo/components/style/properties/longhand/background.mako.rs
servo/components/style/properties/longhand/border.mako.rs
servo/components/style/properties/longhand/box.mako.rs
servo/components/style/properties/longhand/column.mako.rs
servo/components/style/properties/longhand/counters.mako.rs
servo/components/style/properties/longhand/effects.mako.rs
servo/components/style/properties/longhand/font.mako.rs
servo/components/style/properties/longhand/inherited_box.mako.rs
servo/components/style/properties/longhand/inherited_table.mako.rs
servo/components/style/properties/longhand/inherited_text.mako.rs
servo/components/style/properties/longhand/list.mako.rs
servo/components/style/properties/longhand/outline.mako.rs
servo/components/style/properties/longhand/pointing.mako.rs
servo/components/style/properties/longhand/position.mako.rs
servo/components/style/properties/longhand/svg.mako.rs
servo/components/style/properties/longhand/text.mako.rs
servo/components/style/properties/properties.mako.rs
servo/components/style/properties/shorthand/serialize.mako.rs
servo/components/style/values/computed/basic_shape.rs
servo/components/style/values/computed/image.rs
servo/components/style/values/computed/length.rs
servo/components/style/values/computed/mod.rs
servo/components/style/values/computed/position.rs
servo/components/style/values/mod.rs
servo/components/style/values/specified/basic_shape.rs
servo/components/style/values/specified/image.rs
servo/components/style/values/specified/length.rs
servo/components/style/values/specified/mod.rs
servo/components/style/values/specified/position.rs
servo/components/style/viewport.rs
servo/components/style_traits/Cargo.toml
servo/components/style_traits/cursor.rs
servo/components/style_traits/lib.rs
servo/components/style_traits/values.rs
servo/ports/cef/Cargo.lock
servo/ports/geckolib/Cargo.lock
servo/ports/geckolib/glue.rs
servo/ports/geckolib/lib.rs
servo/tests/unit/style/parsing/basic_shape.rs
servo/tests/unit/style/parsing/font.rs
servo/tests/unit/style/parsing/image.rs
servo/tests/unit/style/parsing/mod.rs
servo/tests/unit/style/parsing/position.rs
servo/tests/unit/style/parsing/selectors.rs
servo/tests/unit/style/properties/serialization.rs
servo/tests/unit/stylo/lib.rs
--- a/servo/components/layout/query.rs
+++ b/servo/components/layout/query.rs
@@ -29,17 +29,17 @@ use std::ops::Deref;
 use std::sync::{Arc, Mutex};
 use style::computed_values;
 use style::context::StyleContext;
 use style::logical_geometry::{WritingMode, BlockFlowDirection, InlineBaseDirection};
 use style::properties::longhands::{display, position};
 use style::properties::style_structs;
 use style::selector_impl::PseudoElement;
 use style::selector_matching::Stylist;
-use style::values::LocalToCss;
+use style_traits::ToCss;
 use style_traits::cursor::Cursor;
 use wrapper::{LayoutNodeHelpers, LayoutNodeLayoutData};
 
 /// Mutable data belonging to the LayoutThread.
 ///
 /// This needs to be protected by a mutex so we can do fast RPCs.
 pub struct LayoutThreadData {
     /// The channel on which messages can be sent to the constellation.
--- a/servo/components/script/dom/cssstyledeclaration.rs
+++ b/servo/components/script/dom/cssstyledeclaration.rs
@@ -1,13 +1,12 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-use cssparser::ToCss;
 use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::{self, CSSStyleDeclarationMethods};
 use dom::bindings::error::{Error, ErrorResult, Fallible};
 use dom::bindings::inheritance::Castable;
 use dom::bindings::js::{JS, Root};
 use dom::bindings::reflector::{Reflector, reflect_dom_object};
 use dom::bindings::str::DOMString;
 use dom::element::Element;
 use dom::node::{Node, NodeDamage, window_from_node};
@@ -15,16 +14,17 @@ use dom::window::Window;
 use parking_lot::RwLock;
 use servo_atoms::Atom;
 use std::ascii::AsciiExt;
 use std::sync::Arc;
 use style::parser::ParserContextExtraData;
 use style::properties::{Shorthand, Importance, PropertyDeclarationBlock};
 use style::properties::{is_supported_property, parse_one_declaration, parse_style_attribute};
 use style::selector_impl::PseudoElement;
+use style_traits::ToCss;
 
 // http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface
 #[dom_struct]
 pub struct CSSStyleDeclaration {
     reflector_: Reflector,
     owner: JS<Element>,
     readonly: bool,
     pseudo: Option<PseudoElement>,
--- a/servo/components/script/dom/mediaquerylist.rs
+++ b/servo/components/script/dom/mediaquerylist.rs
@@ -1,13 +1,12 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-use cssparser::ToCss;
 use dom::bindings::cell::DOMRefCell;
 use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
 use dom::bindings::codegen::Bindings::EventListenerBinding::EventListener;
 use dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods;
 use dom::bindings::codegen::Bindings::MediaQueryListBinding::{self, MediaQueryListMethods};
 use dom::bindings::inheritance::Castable;
 use dom::bindings::js::{JS, Root};
 use dom::bindings::reflector::reflect_dom_object;
@@ -17,17 +16,17 @@ use dom::bindings::weakref::{WeakRef, We
 use dom::document::Document;
 use dom::eventtarget::EventTarget;
 use euclid::scale_factor::ScaleFactor;
 use js::jsapi::JSTracer;
 use std::cell::Cell;
 use std::rc::Rc;
 use style;
 use style::media_queries::{Device, MediaType};
-use style_traits::{PagePx, ViewportPx};
+use style_traits::{PagePx, ToCss, ViewportPx};
 
 pub enum MediaQueryListMatchState {
     Same(bool),
     Changed(bool),
 }
 
 #[dom_struct]
 pub struct MediaQueryList {
--- a/servo/components/servo/Cargo.lock
+++ b/servo/components/servo/Cargo.lock
@@ -2424,16 +2424,17 @@ dependencies = [
  "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "syn"
 version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "quote 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
--- a/servo/components/style/custom_properties.rs
+++ b/servo/components/style/custom_properties.rs
@@ -2,23 +2,24 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Support for [custom properties for cascading variables][custom].
 //!
 //! [custom]: https://drafts.csswg.org/css-variables/
 
 use Atom;
-use cssparser::{Delimiter, Parser, SourcePosition, ToCss, Token, TokenSerializationType};
+use cssparser::{Delimiter, Parser, SourcePosition, Token, TokenSerializationType};
 use properties::DeclaredValue;
 use std::ascii::AsciiExt;
 use std::borrow::Cow;
 use std::collections::{HashMap, HashSet};
 use std::fmt;
 use std::sync::Arc;
+use style_traits::ToCss;
 
 // Does not include the `--` prefix
 pub type Name = Atom;
 
 // https://drafts.csswg.org/css-variables/#typedef-custom-property-name
 pub fn parse_name(s: &str) -> Result<&str, ()> {
     if s.starts_with("--") {
         Ok(&s[2..])
--- a/servo/components/style/lib.rs
+++ b/servo/components/style/lib.rs
@@ -127,19 +127,19 @@ mod tid;
 pub mod timer;
 pub mod traversal;
 #[macro_use]
 #[allow(non_camel_case_types)]
 pub mod values;
 pub mod viewport;
 pub mod workqueue;
 
-use cssparser::ToCss;
 use std::fmt;
 use std::sync::Arc;
+use style_traits::ToCss;
 
 #[cfg(feature = "gecko")] pub use gecko_string_cache as string_cache;
 #[cfg(feature = "gecko")] pub use gecko_string_cache::Atom;
 #[cfg(feature = "gecko")] pub use gecko_string_cache::Namespace;
 #[cfg(feature = "gecko")] pub use gecko_string_cache::Atom as Prefix;
 #[cfg(feature = "gecko")] pub use gecko_string_cache::Atom as LocalName;
 
 #[cfg(feature = "servo")] pub use servo_atoms::Atom;
--- a/servo/components/style/media_queries.rs
+++ b/servo/components/style/media_queries.rs
@@ -3,22 +3,22 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! [Media queries][mq].
 //!
 //! [mq]: https://drafts.csswg.org/mediaqueries/
 
 use Atom;
 use app_units::Au;
-use cssparser::{Delimiter, Parser, ToCss, Token};
+use cssparser::{Delimiter, Parser, Token};
 use euclid::size::{Size2D, TypedSize2D};
 use properties::longhands;
 use serialize_comma_separated_list;
 use std::fmt::{self, Write};
-use style_traits::ViewportPx;
+use style_traits::{ToCss, ViewportPx};
 use values::specified;
 
 
 #[derive(Debug, PartialEq)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 pub struct MediaQueryList {
     pub media_queries: Vec<MediaQuery>
 }
--- a/servo/components/style/properties/declaration_block.rs
+++ b/servo/components/style/properties/declaration_block.rs
@@ -1,19 +1,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-use cssparser::{DeclarationListParser, parse_important, ToCss};
+use cssparser::{DeclarationListParser, parse_important};
 use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter};
 use error_reporting::ParseErrorReporter;
 use parser::{ParserContext, ParserContextExtraData, log_css_error};
 use std::ascii::AsciiExt;
 use std::boxed::Box as StdBox;
 use std::fmt;
+use style_traits::ToCss;
 use stylesheets::Origin;
 use super::*;
 use url::Url;
 
 
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub enum Importance {
--- a/servo/components/style/properties/helpers.mako.rs
+++ b/servo/components/style/properties/helpers.mako.rs
@@ -49,19 +49,19 @@
     Setting allow_empty to False allows for cases where the vector
     is empty. The grammar for these is usually "none | <thing> [ , <thing> ]*".
     We assume that the default/initial value is an empty vector for these.
     `initial_value` need not be defined for these.
 </%doc>
 <%def name="vector_longhand(name, gecko_only=False, allow_empty=False, **kwargs)">
     <%call expr="longhand(name, **kwargs)">
         % if product == "gecko" or not gecko_only:
-            use cssparser::ToCss;
             use std::fmt;
             use values::HasViewportPercentage;
+            use style_traits::ToCss;
 
             impl HasViewportPercentage for SpecifiedValue {
                 fn has_viewport_percentage(&self) -> bool {
                     let &SpecifiedValue(ref vec) = self;
                     vec.iter().any(|ref x| x.has_viewport_percentage())
                 }
             }
 
@@ -319,16 +319,17 @@
             'extra_gecko_values', 'extra_servo_values',
             'custom_consts',
         ]}
     %>
 
     <%def name="inner_body()">
         pub use self::computed_value::T as SpecifiedValue;
         pub mod computed_value {
+            use style_traits::ToCss;
             define_css_keyword_enum! { T:
                 % for value in data.longhands_by_name[name].keyword.values_for(product):
                     "${value}" => ${to_rust_ident(value)},
                 % endfor
             }
         }
         #[inline]
         pub fn get_initial_value() -> computed_value::T {
@@ -365,18 +366,18 @@
         ]}
     %>
     <%call expr="longhand(name, keyword=Keyword(name, values, **keyword_kwargs), **kwargs)">
         use values::computed::ComputedValueAsSpecified;
         pub use self::computed_value::T as SpecifiedValue;
         use values::NoViewportPercentage;
         impl NoViewportPercentage for SpecifiedValue {}
         pub mod computed_value {
-            use cssparser::ToCss;
             use std::fmt;
+            use style_traits::ToCss;
 
             #[derive(Debug, Clone, PartialEq)]
             #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
             pub struct T(pub Vec<${to_camel_case(name)}>);
 
             impl ToCss for T {
                 fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
                     debug_assert!(!self.0.is_empty(), "Always parses at least one");
@@ -433,20 +434,21 @@
 <%def name="shorthand(name, sub_properties, experimental=False, **kwargs)">
 <%
     shorthand = data.declare_shorthand(name, sub_properties.split(), experimental=experimental,
                                        **kwargs)
 %>
     % if shorthand:
     pub mod ${shorthand.ident} {
         #[allow(unused_imports)]
-        use cssparser::{Parser, ToCss};
+        use cssparser::Parser;
         use parser::ParserContext;
         use properties::{longhands, PropertyDeclaration, DeclaredValue, Shorthand};
         use std::fmt;
+        use style_traits::ToCss;
 
         pub struct Longhands {
             % for sub_property in shorthand.sub_properties:
                 pub ${sub_property.ident}:
                     Option<longhands::${sub_property.ident}::SpecifiedValue>,
             % endfor
         }
 
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -1,30 +1,31 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use app_units::Au;
-use cssparser::{Color as CSSParserColor, Parser, RGBA, ToCss};
+use cssparser::{Color as CSSParserColor, Parser, RGBA};
 use euclid::{Point2D, Size2D};
 use properties::PropertyDeclaration;
 use properties::longhands;
 use properties::longhands::background_position::computed_value::T as BackgroundPosition;
 use properties::longhands::background_size::computed_value::T as BackgroundSize;
 use properties::longhands::font_weight::computed_value::T as FontWeight;
 use properties::longhands::line_height::computed_value::T as LineHeight;
 use properties::longhands::text_shadow::computed_value::T as TextShadowList;
 use properties::longhands::text_shadow::computed_value::TextShadow;
 use properties::longhands::box_shadow::computed_value::T as BoxShadowList;
 use properties::longhands::box_shadow::single_value::computed_value::T as BoxShadow;
 use properties::longhands::vertical_align::computed_value::T as VerticalAlign;
 use properties::longhands::visibility::computed_value::T as Visibility;
 use properties::longhands::z_index::computed_value::T as ZIndex;
 use std::cmp;
 use std::fmt;
+use style_traits::ToCss;
 use super::ComputedValues;
 use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
 use values::computed::{BorderRadiusSize, LengthOrNone};
 use values::computed::{CalcLengthOrPercentage, LengthOrPercentage};
 use values::computed::position::Position;
 use values::computed::ToComputedValue;
 
 
--- a/servo/components/style/properties/longhand/background.mako.rs
+++ b/servo/components/style/properties/longhand/background.mako.rs
@@ -7,20 +7,19 @@
 <% data.new_style_struct("Background", inherited=False) %>
 
 ${helpers.predefined_type("background-color", "CSSColor",
     "::cssparser::Color::RGBA(::cssparser::RGBA { red: 0., green: 0., blue: 0., alpha: 0. }) /* transparent */",
     animatable=True)}
 
 <%helpers:vector_longhand name="background-image" animatable="False"
                           has_uncacheable_values="${product == 'gecko'}">
-    use cssparser::ToCss;
     use std::fmt;
+    use style_traits::ToCss;
     use values::specified::Image;
-    use values::LocalToCss;
     use values::NoViewportPercentage;
 
     pub mod computed_value {
         use values::computed;
         #[derive(Debug, Clone, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub struct T(pub Option<computed::Image>);
     }
@@ -83,19 +82,18 @@
                 computed_value::T(Some(ref image)) =>
                     SpecifiedValue(Some(ToComputedValue::from_computed_value(image))),
             }
         }
     }
 </%helpers:vector_longhand>
 
 <%helpers:vector_longhand name="background-position" animatable="True">
-        use cssparser::ToCss;
         use std::fmt;
-        use values::LocalToCss;
+        use style_traits::ToCss;
         use values::HasViewportPercentage;
         use values::specified::position::Position;
 
         pub mod computed_value {
             use values::computed::position::Position;
             use properties::animated_properties::{Interpolate, RepeatableListInterpolate};
 
             pub type T = Position;
@@ -144,19 +142,20 @@
                          animatable=False)}
 
 ${helpers.single_keyword("background-origin",
                          "padding-box border-box content-box",
                          vector=True,
                          animatable=False)}
 
 <%helpers:vector_longhand name="background-size" animatable="True">
-    use cssparser::{ToCss, Token};
+    use cssparser::Token;
     use std::ascii::AsciiExt;
     use std::fmt;
+    use style_traits::ToCss;
     use values::HasViewportPercentage;
 
     pub mod computed_value {
         use values::computed::LengthOrPercentageOrAuto;
         use properties::animated_properties::{Interpolate, RepeatableListInterpolate};
 
         #[derive(PartialEq, Clone, Debug)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
--- a/servo/components/style/properties/longhand/border.mako.rs
+++ b/servo/components/style/properties/longhand/border.mako.rs
@@ -19,18 +19,18 @@
     ${helpers.predefined_type("border-%s-style" % side, "BorderStyle",
                               "specified::BorderStyle::none",
                               need_clone=True, animatable=False)}
 % endfor
 
 % for side in ["top", "right", "bottom", "left"]:
     <%helpers:longhand name="border-${side}-width" animatable="True">
         use app_units::Au;
-        use cssparser::ToCss;
         use std::fmt;
+        use style_traits::ToCss;
         use values::HasViewportPercentage;
         use values::specified::BorderWidth;
 
         pub type SpecifiedValue = BorderWidth;
 
         #[inline]
         pub fn parse(_context: &ParserContext, input: &mut Parser)
                      -> Result<SpecifiedValue, ()> {
@@ -62,19 +62,18 @@
 ${helpers.single_keyword("-moz-float-edge", "content-box margin-box",
                          gecko_ffi_name="mFloatEdge",
                          gecko_enum_prefix="StyleFloatEdge",
                          products="gecko",
                          animatable=False)}
 
 // https://drafts.csswg.org/css-backgrounds-3/#border-image-source
 <%helpers:longhand name="border-image-source" products="gecko" animatable="False">
-    use cssparser::ToCss;
     use std::fmt;
-    use values::LocalToCss;
+    use style_traits::ToCss;
     use values::NoViewportPercentage;
     use values::specified::Image;
 
     impl NoViewportPercentage for SpecifiedValue {}
 
     pub mod computed_value {
         use values::computed;
         #[derive(Debug, Clone, PartialEq)]
@@ -134,20 +133,19 @@
         }
 
         Ok(SpecifiedValue(Some(try!(Image::parse(context, input)))))
     }
 </%helpers:longhand>
 
 // https://drafts.csswg.org/css-backgrounds-3/#border-image-outset
 <%helpers:longhand name="border-image-outset" products="gecko" animatable="False">
-    use cssparser::ToCss;
     use std::fmt;
+    use style_traits::ToCss;
     use values::HasViewportPercentage;
-    use values::LocalToCss;
     use values::specified::LengthOrNumber;
 
     impl HasViewportPercentage for SpecifiedValue {
         fn has_viewport_percentage(&self) -> bool {
             let mut viewport_percentage = false;
             for value in self.0.iter() {
                 let vp = value.has_viewport_percentage();
                 viewport_percentage = vp || viewport_percentage;
@@ -248,19 +246,18 @@
         } else {
             Err(())
         }
     }
 </%helpers:longhand>
 
 // https://drafts.csswg.org/css-backgrounds-3/#border-image-repeat
 <%helpers:longhand name="border-image-repeat" products="gecko" animatable="False">
-    use cssparser::ToCss;
     use std::fmt;
-    use values::LocalToCss;
+    use style_traits::ToCss;
     use values::NoViewportPercentage;
 
     impl NoViewportPercentage for SpecifiedValue {}
 
     pub mod computed_value {
         pub use super::RepeatKeyword;
         use values::computed;
 
@@ -322,19 +319,18 @@
         let second = input.try(RepeatKeyword::parse).ok();
 
         Ok(SpecifiedValue(first, second))
     }
 </%helpers:longhand>
 
 // https://drafts.csswg.org/css-backgrounds-3/#border-image-width
 <%helpers:longhand name="border-image-width" products="gecko" animatable="False">
-    use cssparser::ToCss;
     use std::fmt;
-    use values::LocalToCss;
+    use style_traits::ToCss;
     use values::HasViewportPercentage;
     use values::specified::{LengthOrPercentage, Number};
 
     impl HasViewportPercentage for SpecifiedValue {
         fn has_viewport_percentage(&self) -> bool {
             let mut viewport_percentage = false;
             for value in self.0.clone() {
                 let vp = match value {
@@ -518,19 +514,18 @@
         } else {
             Err(())
         }
     }
 </%helpers:longhand>
 
 // https://drafts.csswg.org/css-backgrounds-3/#border-image-slice
 <%helpers:longhand name="border-image-slice" products="gecko" animatable="False">
-    use cssparser::ToCss;
     use std::fmt;
-    use values::LocalToCss;
+    use style_traits::ToCss;
     use values::NoViewportPercentage;
     use values::specified::{Number, Percentage};
 
     impl NoViewportPercentage for SpecifiedValue {}
 
     pub mod computed_value {
         use values::computed::Number;
         use values::specified::Percentage;
--- a/servo/components/style/properties/longhand/box.mako.rs
+++ b/servo/components/style/properties/longhand/box.mako.rs
@@ -22,31 +22,32 @@
             none
         """.split()
         if product == "gecko":
             values += "-moz-box -moz-inline-box".split()
         experimental_values = set("flex".split())
     %>
     pub use self::computed_value::T as SpecifiedValue;
     use values::computed::ComputedValueAsSpecified;
-
+    use style_traits::ToCss;
     use values::NoViewportPercentage;
     impl NoViewportPercentage for SpecifiedValue {}
 
     pub mod computed_value {
+        use style_traits::ToCss;
         #[allow(non_camel_case_types)]
         #[derive(Clone, Eq, PartialEq, Copy, Hash, RustcEncodable, Debug)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
         pub enum T {
             % for value in values:
                 ${to_rust_ident(value)},
             % endfor
         }
 
-        impl ::cssparser::ToCss for T {
+        impl ToCss for T {
             fn to_css<W>(&self, dest: &mut W) -> ::std::fmt::Result
             where W: ::std::fmt::Write {
                 match *self {
                     % for value in values:
                         T::${to_rust_ident(value)} => dest.write_str("${value}"),
                     % endfor
                 }
             }
@@ -143,26 +144,26 @@
         let d = context.style().get_box().clone_display();
         context.mutate_style().mutate_box().set__servo_display_for_hypothetical_box(d);
     }
 
 </%helpers:longhand>
 
 <%helpers:longhand name="vertical-align"
                    animatable="True">
-  use cssparser::ToCss;
   use std::fmt;
+  use style_traits::ToCss;
+  use values::HasViewportPercentage;
 
   <% vertical_align = data.longhands_by_name["vertical-align"] %>
   <% vertical_align.keyword = Keyword("vertical-align",
                                       "baseline sub super top text-top middle bottom text-bottom",
                                       extra_gecko_values="middle-with-baseline") %>
   <% vertical_align_keywords = vertical_align.keyword.values_for(product) %>
 
-  use values::HasViewportPercentage;
   impl HasViewportPercentage for SpecifiedValue {
       fn has_viewport_percentage(&self) -> bool {
           match *self {
               SpecifiedValue::LengthOrPercentage(length) => length.has_viewport_percentage(),
               _ => false
           }
       }
   }
@@ -199,28 +200,28 @@
               % endfor
               _ => Err(())
           }
       })
   }
   pub mod computed_value {
       use app_units::Au;
       use std::fmt;
-      use values::LocalToCss;
+      use style_traits::ToCss;
       use values::{CSSFloat, computed};
       #[allow(non_camel_case_types)]
       #[derive(PartialEq, Copy, Clone, Debug)]
       #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
       pub enum T {
           % for keyword in vertical_align_keywords:
               ${to_rust_ident(keyword)},
           % endfor
           LengthOrPercentage(computed::LengthOrPercentage),
       }
-      impl ::cssparser::ToCss for T {
+      impl ToCss for T {
           fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
               match *self {
                   % for keyword in vertical_align_keywords:
                       T::${to_rust_ident(keyword)} => dest.write_str("${keyword}"),
                   % endfor
                   T::LengthOrPercentage(value) => value.to_css(dest),
               }
           }
@@ -277,23 +278,23 @@
                          gecko_constant_prefix="NS_STYLE_OVERFLOW")}
 
 // FIXME(pcwalton, #2742): Implement scrolling for `scroll` and `auto`.
 <%helpers:longhand name="overflow-y"
                    need_clone="True"
                    animatable="False">
   use super::overflow_x;
 
-  use cssparser::ToCss;
   use std::fmt;
+  use style_traits::ToCss;
   use values::computed::ComputedValueAsSpecified;
+  use values::NoViewportPercentage;
 
   pub use self::computed_value::T as SpecifiedValue;
 
-  use values::NoViewportPercentage;
   impl NoViewportPercentage for SpecifiedValue {}
 
   impl ToCss for SpecifiedValue {
       fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
           self.0.to_css(dest)
       }
   }
 
@@ -322,18 +323,18 @@
     use values::specified::Time;
 
     pub use self::computed_value::T as SpecifiedValue;
     pub use values::specified::Time as SingleSpecifiedValue;
     use values::NoViewportPercentage;
     impl NoViewportPercentage for SpecifiedValue {}
 
     pub mod computed_value {
-        use cssparser::ToCss;
         use std::fmt;
+        use style_traits::ToCss;
         use values::computed::{Context, ToComputedValue};
 
         pub use values::computed::Time as SingleComputedValue;
 
         #[derive(Debug, Clone, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub struct T(pub Vec<SingleComputedValue>);
 
@@ -421,19 +422,19 @@
     }
 
     static STEP_START: TransitionTimingFunction =
         TransitionTimingFunction::Steps(1, StartEnd::Start);
     static STEP_END: TransitionTimingFunction =
         TransitionTimingFunction::Steps(1, StartEnd::End);
 
     pub mod computed_value {
-        use cssparser::ToCss;
         use euclid::point::Point2D;
         use std::fmt;
+        use style_traits::ToCss;
         use values::computed::ComputedValueAsSpecified;
 
         pub use self::TransitionTimingFunction as SingleComputedValue;
 
         #[derive(Copy, Clone, Debug, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub enum TransitionTimingFunction {
             CubicBezier(Point2D<f32>, Point2D<f32>),
@@ -576,18 +577,18 @@
                    animatable="False">
 
     use values::computed::ComputedValueAsSpecified;
 
     pub use self::computed_value::SingleComputedValue as SingleSpecifiedValue;
     pub use self::computed_value::T as SpecifiedValue;
 
     pub mod computed_value {
-        use cssparser::ToCss;
         use std::fmt;
+        use style_traits::ToCss;
         // NB: Can't generate the type here because it needs all the longhands
         // generated beforehand.
         pub use properties::animated_properties::TransitionProperty;
         pub use properties::animated_properties::TransitionProperty as SingleComputedValue;
 
         #[derive(Clone, Debug, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub struct T(pub Vec<SingleComputedValue>);
@@ -641,19 +642,19 @@
 <%helpers:longhand name="animation-name"
                    need_index="True"
                    animatable="False",
                    allowed_in_keyframe_block="False">
     use values::computed::ComputedValueAsSpecified;
     use values::NoViewportPercentage;
 
     pub mod computed_value {
-        use cssparser::ToCss;
         use std::fmt;
         use Atom;
+        use style_traits::ToCss;
 
         pub use Atom as SingleComputedValue;
 
         #[derive(Debug, Clone, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub struct T(pub Vec<Atom>);
 
         impl ToCss for T {
@@ -727,18 +728,18 @@
 <%helpers:longhand name="animation-iteration-count"
                    need_index="True"
                    animatable="False",
                    allowed_in_keyframe_block="False">
     use values::computed::ComputedValueAsSpecified;
     use values::NoViewportPercentage;
 
     pub mod computed_value {
-        use cssparser::ToCss;
         use std::fmt;
+        use style_traits::ToCss;
 
         pub use self::AnimationIterationCount as SingleComputedValue;
 
         #[derive(Debug, Clone, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub enum AnimationIterationCount {
             Number(u32),
             Infinite,
@@ -837,19 +838,18 @@
     pub use super::transition_duration::computed_value;
     pub use super::transition_duration::{get_initial_value, get_initial_single_value};
     pub use super::transition_duration::{parse, parse_one};
     pub use super::transition_duration::SpecifiedValue;
     pub use super::transition_duration::SingleSpecifiedValue;
 </%helpers:longhand>
 
 <%helpers:longhand products="gecko" name="scroll-snap-points-y" animatable="False">
-    use cssparser::ToCss;
     use std::fmt;
-    use values::LocalToCss;
+    use style_traits::ToCss;
     use values::HasViewportPercentage;
     use values::specified::LengthOrPercentage;
 
     impl HasViewportPercentage for SpecifiedValue {
         fn has_viewport_percentage(&self) -> bool {
             match *self {
                 SpecifiedValue::Repeat(length) => length.has_viewport_percentage(),
                 _ => false
--- a/servo/components/style/properties/longhand/column.mako.rs
+++ b/servo/components/style/properties/longhand/column.mako.rs
@@ -3,19 +3,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 <%namespace name="helpers" file="/helpers.mako.rs" />
 
 <% data.new_style_struct("Column", inherited=False) %>
 
 // FIXME: This prop should be animatable.
 <%helpers:longhand name="column-width" experimental="True" animatable="False">
-    use cssparser::ToCss;
     use std::fmt;
-    use values::LocalToCss;
+    use style_traits::ToCss;
     use values::HasViewportPercentage;
 
     impl HasViewportPercentage for SpecifiedValue {
         fn has_viewport_percentage(&self) -> bool {
             match *self {
                 SpecifiedValue::Specified(length) => length.has_viewport_percentage(),
                 _ => false
             }
@@ -86,18 +85,18 @@
         } else {
             specified::Length::parse_non_negative(input).map(SpecifiedValue::Specified)
         }
     }
 </%helpers:longhand>
 
 // FIXME: This prop should be animatable.
 <%helpers:longhand name="column-count" experimental="True" animatable="False">
-    use cssparser::ToCss;
     use std::fmt;
+    use style_traits::ToCss;
     use values::NoViewportPercentage;
 
     impl NoViewportPercentage for SpecifiedValue {}
 
     #[derive(Debug, Clone, Copy, PartialEq)]
     #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
     pub enum SpecifiedValue {
         Auto,
@@ -166,19 +165,18 @@
             }
             Ok(SpecifiedValue::Specified(count as u32))
         }
     }
 </%helpers:longhand>
 
 // FIXME: This prop should be animatable.
 <%helpers:longhand name="column-gap" experimental="True" products="servo" animatable="False">
-    use cssparser::ToCss;
     use std::fmt;
-    use values::LocalToCss;
+    use style_traits::ToCss;
     use values::HasViewportPercentage;
 
     impl HasViewportPercentage for SpecifiedValue {
         fn has_viewport_percentage(&self) -> bool {
             match *self {
                 SpecifiedValue::Specified(length) => length.has_viewport_percentage(),
                 _ => false
             }
--- a/servo/components/style/properties/longhand/counters.mako.rs
+++ b/servo/components/style/properties/longhand/counters.mako.rs
@@ -18,18 +18,19 @@
     pub use self::computed_value::ContentItem;
 
     impl ComputedValueAsSpecified for SpecifiedValue {}
     impl NoViewportPercentage for SpecifiedValue {}
 
     pub mod computed_value {
         use super::super::list_style_type;
 
-        use cssparser::{self, ToCss};
+        use cssparser;
         use std::fmt;
+        use style_traits::ToCss;
 
         #[derive(Debug, PartialEq, Eq, Clone)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub enum ContentItem {
             /// Literal string content.
             String(String),
             /// `counter(name, style)`.
             Counter(String, list_style_type::computed_value::T),
@@ -170,21 +171,22 @@
         } else {
             Err(())
         }
     }
 </%helpers:longhand>
 
 <%helpers:longhand name="counter-increment" products="servo" animatable="False">
     use std::fmt;
+    use style_traits::ToCss;
     use super::content;
     use values::NoViewportPercentage;
     use values::computed::ComputedValueAsSpecified;
 
-    use cssparser::{ToCss, Token, serialize_identifier};
+    use cssparser::{Token, serialize_identifier};
     use std::borrow::{Cow, ToOwned};
 
     pub use self::computed_value::T as SpecifiedValue;
 
     pub mod computed_value {
         #[derive(Debug, Clone, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub struct T(pub Vec<(String,i32)>);
--- a/servo/components/style/properties/longhand/effects.mako.rs
+++ b/servo/components/style/properties/longhand/effects.mako.rs
@@ -8,20 +8,20 @@
 <% data.new_style_struct("Effects", inherited=False) %>
 
 ${helpers.predefined_type("opacity",
                           "Opacity",
                           "1.0",
                           animatable=True)}
 
 <%helpers:vector_longhand name="box-shadow" allow_empty="True" animatable="True">
-    use cssparser::{self, ToCss};
+    use cssparser;
     use std::fmt;
     use parser::Parse;
-    use values::LocalToCss;
+    use style_traits::ToCss;
     use values::HasViewportPercentage;
 
     #[derive(Debug, Clone, PartialEq)]
     #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
     pub struct SpecifiedValue {
         pub offset_x: specified::Length,
         pub offset_y: specified::Length,
         pub blur_radius: specified::Length,
@@ -184,19 +184,18 @@
             color: color,
             inset: inset,
         })
     }
 </%helpers:vector_longhand>
 
 // FIXME: This prop should be animatable
 <%helpers:longhand name="clip" products="servo" animatable="False">
-    use cssparser::ToCss;
     use std::fmt;
-    use values::LocalToCss;
+    use style_traits::ToCss;
     use values::HasViewportPercentage;
 
     // NB: `top` and `left` are 0 if `auto` per CSS 2.1 11.1.2.
 
     pub mod computed_value {
         use app_units::Au;
         use properties::animated_properties::Interpolate;
 
@@ -400,21 +399,19 @@
             })))
         })
     }
 </%helpers:longhand>
 
 // FIXME: This prop should be animatable
 <%helpers:longhand name="filter" animatable="False">
     //pub use self::computed_value::T as SpecifiedValue;
-    use cssparser::ToCss;
     use std::fmt;
-    use values::LocalToCss;
-    use values::CSSFloat;
-    use values::HasViewportPercentage;
+    use style_traits::ToCss;
+    use values::{CSSFloat, HasViewportPercentage};
     use values::specified::{Angle, Length};
 
     impl HasViewportPercentage for SpecifiedValue {
         fn has_viewport_percentage(&self) -> bool {
             let &SpecifiedValue(ref vec) = self;
             vec.iter().any(|ref x| x.has_viewport_percentage())
         }
     }
@@ -670,21 +667,19 @@
                 }
             }).collect())
         }
     }
 </%helpers:longhand>
 
 <%helpers:longhand name="transform" products="servo" animatable="True">
     use app_units::Au;
-    use values::CSSFloat;
-    use values::HasViewportPercentage;
-
-    use cssparser::ToCss;
     use std::fmt;
+    use style_traits::ToCss;
+    use values::{CSSFloat, HasViewportPercentage};
 
     pub mod computed_value {
         use values::CSSFloat;
         use values::computed;
 
         #[derive(Clone, Copy, Debug, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub struct ComputedMatrix {
@@ -1288,23 +1283,21 @@ pub fn parse_origin(_: &ParserContext, i
                          animatable=False)}
 
 ${helpers.single_keyword("transform-style",
                          "auto flat preserve-3d",
                          animatable=False)}
 
 <%helpers:longhand name="transform-origin" products="servo" animatable="True">
     use app_units::Au;
-    use values::LocalToCss;
+    use std::fmt;
+    use style_traits::ToCss;
     use values::HasViewportPercentage;
     use values::specified::{Length, LengthOrPercentage, Percentage};
 
-    use cssparser::ToCss;
-    use std::fmt;
-
     pub mod computed_value {
         use properties::animated_properties::Interpolate;
         use values::computed::{Length, LengthOrPercentage};
 
         #[derive(Clone, Copy, Debug, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub struct T {
             pub horizontal: LengthOrPercentage,
@@ -1403,22 +1396,21 @@ pub fn parse_origin(_: &ParserContext, i
 ${helpers.predefined_type("perspective",
                           "LengthOrNone",
                           "computed::LengthOrNone::None",
                           products="servo",
                           animatable=True)}
 
 // FIXME: This prop should be animatable
 <%helpers:longhand name="perspective-origin" products="servo" animatable="False">
+    use std::fmt;
+    use style_traits::ToCss;
     use values::HasViewportPercentage;
     use values::specified::{LengthOrPercentage, Percentage};
 
-    use cssparser::ToCss;
-    use std::fmt;
-
     pub mod computed_value {
         use values::computed::LengthOrPercentage;
 
         #[derive(Clone, Copy, Debug, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub struct T {
             pub horizontal: LengthOrPercentage,
             pub vertical: LengthOrPercentage,
--- a/servo/components/style/properties/longhand/font.mako.rs
+++ b/servo/components/style/properties/longhand/font.mako.rs
@@ -13,19 +13,19 @@
     use values::NoViewportPercentage;
     use values::computed::ComputedValueAsSpecified;
     pub use self::computed_value::T as SpecifiedValue;
 
     impl ComputedValueAsSpecified for SpecifiedValue {}
     impl NoViewportPercentage for SpecifiedValue {}
 
     pub mod computed_value {
-        use cssparser::ToCss;
         use std::fmt;
         use Atom;
+        use style_traits::ToCss;
 
         #[derive(Debug, PartialEq, Eq, Clone, Hash)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
         pub enum FontFamily {
             FamilyName(Atom),
             Generic(Atom),
         }
         impl FontFamily {
@@ -132,18 +132,18 @@
                          gecko_ffi_name="mFont.style",
                          animatable=False)}
 
 ${helpers.single_keyword("font-variant",
                          "normal small-caps",
                          animatable=False)}
 
 <%helpers:longhand name="font-weight" need_clone="True" animatable="True">
-    use cssparser::ToCss;
     use std::fmt;
+    use style_traits::ToCss;
     use values::NoViewportPercentage;
 
     impl NoViewportPercentage for SpecifiedValue {}
 
     #[derive(Debug, Clone, PartialEq, Eq, Copy)]
     #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
     pub enum SpecifiedValue {
         Bolder,
@@ -266,20 +266,19 @@
                 % endfor
             }
         }
     }
 </%helpers:longhand>
 
 <%helpers:longhand name="font-size" need_clone="True" animatable="True">
     use app_units::Au;
-    use cssparser::ToCss;
     use std::fmt;
-    use values::FONT_MEDIUM_PX;
-    use values::HasViewportPercentage;
+    use style_traits::ToCss;
+    use values::{FONT_MEDIUM_PX, HasViewportPercentage};
     use values::specified::{LengthOrPercentage, Length, Percentage};
 
     impl ToCss for SpecifiedValue {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             self.0.to_css(dest)
         }
     }
 
@@ -346,21 +345,20 @@
                 .ok_or(())
                 .map(specified::LengthOrPercentage::Length)
         })
         .map(SpecifiedValue)
     }
 </%helpers:longhand>
 
 <%helpers:longhand products="gecko" name="font-synthesis" animatable="False">
-    use cssparser::ToCss;
     use std::fmt;
-    use values::LocalToCss;
+    use style_traits::ToCss;
+    use values::NoViewportPercentage;
     use values::computed::ComputedValueAsSpecified;
-    use values::NoViewportPercentage;
 
     impl ComputedValueAsSpecified for SpecifiedValue {}
     impl NoViewportPercentage for SpecifiedValue {}
 
     pub mod computed_value {
         pub use super::SpecifiedValue as T;
     }
 
@@ -433,29 +431,29 @@
 ${helpers.single_keyword("font-variant-position",
                          "normal sub super",
                          products="gecko",
                          gecko_ffi_name="mFont.variantPosition",
                          gecko_constant_prefix="NS_FONT_VARIANT_POSITION",
                          animatable=False)}
 
 <%helpers:longhand name="font-feature-settings" products="none" animatable="False">
-    use cssparser::ToCss;
     use std::fmt;
+    use style_traits::ToCss;
     use values::NoViewportPercentage;
     use values::computed::ComputedValueAsSpecified;
     pub use self::computed_value::T as SpecifiedValue;
 
     impl ComputedValueAsSpecified for SpecifiedValue {}
     impl NoViewportPercentage for SpecifiedValue {}
 
     pub mod computed_value {
-        use cssparser::ToCss;
         use cssparser::Parser;
         use std::fmt;
+        use style_traits::ToCss;
 
         #[derive(Debug, Clone, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub enum T {
             Normal,
             Tag(Vec<FeatureTagValue>)
         }
 
@@ -550,18 +548,18 @@
     use values::NoViewportPercentage;
     use values::computed::ComputedValueAsSpecified;
     pub use self::computed_value::T as SpecifiedValue;
 
     impl ComputedValueAsSpecified for SpecifiedValue {}
     impl NoViewportPercentage for SpecifiedValue {}
 
     pub mod computed_value {
-        use cssparser::ToCss;
         use std::fmt;
+        use style_traits::ToCss;
 
         impl ToCss for T {
             fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
                 match *self {
                     T::Normal => dest.write_str("normal"),
                     T::Override(ref lang) => write!(dest, "\"{}\"", lang),
                 }
             }
--- a/servo/components/style/properties/longhand/inherited_box.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_box.mako.rs
@@ -51,18 +51,18 @@
                          animatable=False)}
 
 // Used in the bottom-up flow construction traversal to avoid constructing flows for
 // descendants of nodes with `display: none`.
 <%helpers:longhand name="-servo-under-display-none"
                    derived_from="display"
                    products="servo"
                    animatable="False">
-    use cssparser::ToCss;
     use std::fmt;
+    use style_traits::ToCss;
     use values::computed::ComputedValueAsSpecified;
     use values::NoViewportPercentage;
 
     impl NoViewportPercentage for SpecifiedValue {}
 
     #[derive(Copy, Clone, Debug, Eq, PartialEq)]
     #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
     pub struct SpecifiedValue(pub bool);
--- a/servo/components/style/properties/longhand/inherited_table.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_table.mako.rs
@@ -13,22 +13,20 @@
                          gecko_constant_prefix="NS_STYLE_TABLE_EMPTY_CELLS",
                          animatable=False)}
 ${helpers.single_keyword("caption-side", "top bottom",
                          extra_gecko_values="right left top-outside bottom-outside",
                          animatable=False)}
 
 <%helpers:longhand name="border-spacing" animatable="False">
     use app_units::Au;
-    use values::LocalToCss;
+    use std::fmt;
+    use style_traits::ToCss;
     use values::HasViewportPercentage;
 
-    use cssparser::ToCss;
-    use std::fmt;
-
     pub mod computed_value {
         use app_units::Au;
         use properties::animated_properties::Interpolate;
 
         #[derive(Clone, Copy, Debug, PartialEq, RustcEncodable)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub struct T {
             pub horizontal: Au,
--- a/servo/components/style/properties/longhand/inherited_text.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_text.mako.rs
@@ -2,21 +2,19 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 <%namespace name="helpers" file="/helpers.mako.rs" />
 
 <% data.new_style_struct("InheritedText", inherited=True, gecko_name="Text") %>
 
 <%helpers:longhand name="line-height" animatable="True">
-    use cssparser::ToCss;
     use std::fmt;
-    use values::LocalToCss;
-    use values::CSSFloat;
-    use values::HasViewportPercentage;
+    use style_traits::ToCss;
+    use values::{CSSFloat, HasViewportPercentage};
 
     impl HasViewportPercentage for SpecifiedValue {
         fn has_viewport_percentage(&self) -> bool {
             match *self {
                 SpecifiedValue::LengthOrPercentage(length) => length.has_viewport_percentage(),
                 _ => false
             }
         }
@@ -148,16 +146,17 @@
 
 <%helpers:longhand name="text-align" animatable="False">
     pub use self::computed_value::T as SpecifiedValue;
     use values::computed::ComputedValueAsSpecified;
     use values::NoViewportPercentage;
     impl ComputedValueAsSpecified for SpecifiedValue {}
     impl NoViewportPercentage for SpecifiedValue {}
     pub mod computed_value {
+        use style_traits::ToCss;
         macro_rules! define_text_align {
             ( $( $name: ident ( $string: expr ) => $discriminant: expr, )+ ) => {
                 define_css_keyword_enum! { T:
                     $(
                         $string => $name,
                     )+
                 }
                 impl T {
@@ -204,19 +203,18 @@
     pub fn parse(_context: &ParserContext, input: &mut Parser)
                  -> Result<SpecifiedValue, ()> {
         computed_value::T::parse(input)
     }
 </%helpers:longhand>
 
 // FIXME: This prop should be animatable.
 <%helpers:longhand name="letter-spacing" animatable="False">
-    use cssparser::ToCss;
     use std::fmt;
-    use values::LocalToCss;
+    use style_traits::ToCss;
     use values::HasViewportPercentage;
 
     impl HasViewportPercentage for SpecifiedValue {
         fn has_viewport_percentage(&self) -> bool {
             match *self {
                 SpecifiedValue::Specified(length) => length.has_viewport_percentage(),
                 _ => false
             }
@@ -285,19 +283,18 @@
             Ok(SpecifiedValue::Normal)
         } else {
             specified::Length::parse_non_negative(input).map(SpecifiedValue::Specified)
         }
     }
 </%helpers:longhand>
 
 <%helpers:longhand name="word-spacing" animatable="False">
-    use cssparser::ToCss;
     use std::fmt;
-    use values::LocalToCss;
+    use style_traits::ToCss;
     use values::HasViewportPercentage;
 
     impl HasViewportPercentage for SpecifiedValue {
         fn has_viewport_percentage(&self) -> bool {
             match *self {
                 SpecifiedValue::Specified(length) => length.has_viewport_percentage(),
                 _ => false
             }
@@ -400,20 +397,20 @@
                          products="gecko",
                          gecko_constant_prefix="NS_STYLE_TEXT_ALIGN",
                          animatable=False)}
 
 <%helpers:longhand name="-servo-text-decorations-in-effect"
                    derived_from="display text-decoration"
                    need_clone="True" products="servo"
                    animatable="False">
-    use cssparser::{RGBA, ToCss};
+    use cssparser::RGBA;
     use std::fmt;
-
-    use values:: NoViewportPercentage;
+    use style_traits::ToCss;
+    use values::NoViewportPercentage;
     use values::computed::ComputedValueAsSpecified;
 
     impl ComputedValueAsSpecified for SpecifiedValue {}
     impl NoViewportPercentage for SpecifiedValue {}
 
     #[derive(Clone, PartialEq, Copy, Debug)]
     #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
     pub struct SpecifiedValue {
@@ -524,19 +521,19 @@
                 SpecifiedValue::pre |
                 SpecifiedValue::pre_wrap => true,
             }
         }
     }
 </%helpers:single_keyword_computed>
 
 <%helpers:longhand name="text-shadow" animatable="True">
-    use cssparser::{self, ToCss};
+    use cssparser;
     use std::fmt;
-    use values::LocalToCss;
+    use style_traits::ToCss;
     use values::HasViewportPercentage;
 
     impl HasViewportPercentage for SpecifiedValue {
         fn has_viewport_percentage(&self) -> bool {
             let &SpecifiedValue(ref vec) = self;
             vec.iter().any(|ref x| x .has_viewport_percentage())
         }
     }
@@ -734,20 +731,19 @@
                 }
             }).collect())
         }
     }
 </%helpers:longhand>
 
 <%helpers:longhand name="text-emphasis-style" products="gecko" need_clone="True" animatable="False">
     use computed_values::writing_mode::T as writing_mode;
-    use cssparser::ToCss;
     use std::fmt;
+    use style_traits::ToCss;
     use unicode_segmentation::UnicodeSegmentation;
-    use values::LocalToCss;
     use values::NoViewportPercentage;
 
     impl NoViewportPercentage for SpecifiedValue {}
 
     pub mod computed_value {
         #[derive(Debug, Clone, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub enum T {
--- a/servo/components/style/properties/longhand/list.mako.rs
+++ b/servo/components/style/properties/longhand/list.mako.rs
@@ -26,22 +26,22 @@
     gecko_constant_prefix="NS_STYLE_LIST_STYLE",
     animatable=False)}
 
 ${helpers.predefined_type("list-style-image", "UrlOrNone", "computed_value::T::None",
                           needs_context=True,
                           animatable="False")}
 
 <%helpers:longhand name="quotes" animatable="False">
+    use cssparser::Token;
     use std::borrow::Cow;
     use std::fmt;
-    use values::NoViewportPercentage;
+    use style_traits::ToCss;
     use values::computed::ComputedValueAsSpecified;
-
-    use cssparser::{ToCss, Token};
+    use values::NoViewportPercentage;
 
     pub use self::computed_value::T as SpecifiedValue;
 
     pub mod computed_value {
         #[derive(Debug, Clone, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub struct T(pub Vec<(String,String)>);
     }
--- a/servo/components/style/properties/longhand/outline.mako.rs
+++ b/servo/components/style/properties/longhand/outline.mako.rs
@@ -24,19 +24,18 @@
             Ok(SpecifiedValue::hidden) => Err(()),
             result => result
         }
     }
 </%helpers:longhand>
 
 <%helpers:longhand name="outline-width" animatable="True">
     use app_units::Au;
-    use cssparser::ToCss;
     use std::fmt;
-    use values::LocalToCss;
+    use style_traits::ToCss;
     use values::HasViewportPercentage;
 
     impl ToCss for SpecifiedValue {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             self.0.to_css(dest)
         }
     }
 
--- a/servo/components/style/properties/longhand/pointing.mako.rs
+++ b/servo/components/style/properties/longhand/pointing.mako.rs
@@ -10,19 +10,19 @@
     pub use self::computed_value::T as SpecifiedValue;
     use values::NoViewportPercentage;
     use values::computed::ComputedValueAsSpecified;
 
     impl ComputedValueAsSpecified for SpecifiedValue {}
     impl NoViewportPercentage for SpecifiedValue {}
 
     pub mod computed_value {
-        use cssparser::ToCss;
         use std::fmt;
         use style_traits::cursor::Cursor;
+        use style_traits::ToCss;
 
         #[derive(Clone, PartialEq, Eq, Copy, Debug)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub enum T {
             AutoCursor,
             SpecifiedCursor(Cursor),
         }
 
--- a/servo/components/style/properties/longhand/position.mako.rs
+++ b/servo/components/style/properties/longhand/position.mako.rs
@@ -15,18 +15,18 @@
 <%helpers:longhand name="z-index" animatable="True">
     use values::NoViewportPercentage;
     use values::computed::ComputedValueAsSpecified;
 
     impl ComputedValueAsSpecified for SpecifiedValue {}
     impl NoViewportPercentage for SpecifiedValue {}
     pub type SpecifiedValue = computed_value::T;
     pub mod computed_value {
-        use cssparser::ToCss;
         use std::fmt;
+        use style_traits::ToCss;
 
         #[derive(PartialEq, Clone, Eq, Copy, Debug)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub enum T {
             Auto,
             Number(i32),
         }
 
--- a/servo/components/style/properties/longhand/svg.mako.rs
+++ b/servo/components/style/properties/longhand/svg.mako.rs
@@ -46,19 +46,18 @@
     animatable=False)}
 
 // CSS Masking Module Level 1
 // https://www.w3.org/TR/css-masking-1/
 ${helpers.single_keyword("mask-type", "luminance alpha",
                          products="gecko", animatable=False)}
 
 <%helpers:longhand name="clip-path" animatable="False" products="gecko">
-    use cssparser::ToCss;
     use std::fmt;
-    use values::LocalToCss;
+    use style_traits::ToCss;
     use values::NoViewportPercentage;
     use values::specified::basic_shape::{ShapeSource, GeometryBox};
 
     pub mod computed_value {
         use app_units::Au;
         use values::computed::basic_shape::{ShapeSource, GeometryBox};
 
         pub type T = ShapeSource<GeometryBox>;
@@ -143,28 +142,27 @@
 ${helpers.single_keyword("mask-composite",
                          "add subtract intersect exclude",
                          vector=True,
                          products="gecko",
                          animatable=False)}
 
 <%helpers:vector_longhand name="mask-image" products="gecko" animatable="False"
                           has_uncacheable_values="${product == 'gecko'}">
-    use cssparser::ToCss;
     use std::fmt;
+    use style_traits::ToCss;
     use url::Url;
     use values::specified::{Image, UrlExtraData};
-    use values::LocalToCss;
     use values::NoViewportPercentage;
 
     pub mod computed_value {
-        use cssparser::ToCss;
         use std::fmt;
+        use style_traits::ToCss;
         use url::Url;
-        use values::{computed, LocalToCss};
+        use values::computed;
         #[derive(Debug, Clone, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub enum T {
             Image(computed::Image),
             Url(Url, computed::UrlExtraData),
             None
         }
 
--- a/servo/components/style/properties/longhand/text.mako.rs
+++ b/servo/components/style/properties/longhand/text.mako.rs
@@ -11,20 +11,20 @@
                          additional_methods=[Method("has_underline", "bool"),
                                              Method("has_overline", "bool"),
                                              Method("has_line_through", "bool")]) %>
 
 % if product == "servo":
     ${helpers.single_keyword("text-overflow", "clip ellipsis", animatable=False)}
 % else:
 <%helpers:longhand name="text-overflow" animatable="False">
-    use cssparser::ToCss;
     use std::fmt;
+    use style_traits::ToCss;
+    use values::NoViewportPercentage;
     use values::computed::ComputedValueAsSpecified;
-    use values::NoViewportPercentage;
 
     impl ComputedValueAsSpecified for SpecifiedValue {}
     impl NoViewportPercentage for SpecifiedValue {}
 
     #[derive(PartialEq, Eq, Clone, Debug)]
     #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
     pub enum Side {
         Clip,
@@ -99,20 +99,20 @@
                          "normal embed isolate bidi-override isolate-override plaintext",
                          animatable=False)}
 
 // FIXME: This prop should be animatable.
 <%helpers:longhand name="${'text-decoration' if product == 'servo' else 'text-decoration-line'}"
                    custom_cascade="${product == 'servo'}"
                    animatable="False"
                    disable_when_testing="True">
-    use cssparser::ToCss;
     use std::fmt;
+    use style_traits::ToCss;
+    use values::NoViewportPercentage;
     use values::computed::ComputedValueAsSpecified;
-    use values::NoViewportPercentage;
 
     impl ComputedValueAsSpecified for SpecifiedValue {}
     impl NoViewportPercentage for SpecifiedValue {}
 
     #[derive(PartialEq, Eq, Copy, Clone, Debug)]
     #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
     pub struct SpecifiedValue {
         pub underline: bool,
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -14,29 +14,28 @@ use std::ascii::AsciiExt;
 use std::boxed::Box as StdBox;
 use std::collections::HashSet;
 use std::fmt::{self, Write};
 use std::sync::Arc;
 
 use Atom;
 use app_units::Au;
 #[cfg(feature = "servo")] use cssparser::{Color as CSSParserColor, RGBA};
-use cssparser::{Parser, ToCss, TokenSerializationType};
+use cssparser::{Parser, TokenSerializationType};
 use error_reporting::ParseErrorReporter;
 use url::Url;
 #[cfg(feature = "servo")] use euclid::side_offsets::SideOffsets2D;
 use euclid::size::Size2D;
 use computed_values;
 #[cfg(feature = "servo")] use logical_geometry::{LogicalMargin, PhysicalSide};
 use logical_geometry::WritingMode;
 use parser::{ParserContext, ParserContextExtraData};
+use style_traits::ToCss;
 use stylesheets::Origin;
-#[cfg(feature = "servo")] use values::LocalToCss;
-use values::HasViewportPercentage;
-use values::computed;
+use values::{HasViewportPercentage, computed};
 use cascade_info::CascadeInfo;
 use rule_tree::StrongRuleNode;
 #[cfg(feature = "servo")] use values::specified::BorderStyle;
 
 use self::property_bit_field::PropertyBitField;
 pub use self::declaration_block::*;
 
 <%!
--- a/servo/components/style/properties/shorthand/serialize.mako.rs
+++ b/servo/components/style/properties/shorthand/serialize.mako.rs
@@ -1,14 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-use cssparser::ToCss;
 use properties::{AppendableValue, DeclaredValue, PropertyDeclaration, Shorthand};
+use style_traits::ToCss;
 use values::specified::{BorderStyle, CSSColor};
 use std::fmt;
 
 pub fn serialize_four_sides<W, I>(dest: &mut W, top: &I, right: &I, bottom: &I, left: &I)
     -> fmt::Result where W: fmt::Write, I: ToCss + PartialEq {
 
     if left == right {
         let horizontal_value = left;
--- a/servo/components/style/values/computed/basic_shape.rs
+++ b/servo/components/style/values/computed/basic_shape.rs
@@ -2,19 +2,19 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! CSS handling for the computed value of
 //! [`basic-shape`][basic-shape]s
 //!
 //! [basic-shape]: https://drafts.csswg.org/css-shapes/#typedef-basic-shape
 
-use cssparser::ToCss;
 use properties::shorthands::serialize_four_sides;
 use std::fmt;
+use style_traits::ToCss;
 use url::Url;
 use values::computed::{BorderRadiusSize, LengthOrPercentage};
 use values::computed::UrlExtraData;
 use values::computed::position::Position;
 
 pub use values::specified::basic_shape::{FillRule, GeometryBox, ShapeBox};
 
 #[derive(Clone, PartialEq, Debug)]
@@ -29,17 +29,16 @@ pub enum ShapeSource<T> {
 impl<T> Default for ShapeSource<T> {
     fn default() -> Self {
         ShapeSource::None
     }
 }
 
 impl<T: ToCss> ToCss for ShapeSource<T> {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-        use values::LocalToCss;
         match *self {
             ShapeSource::Url(ref url, _) => url.to_css(dest),
             ShapeSource::Shape(ref shape, Some(ref reference)) => {
                 try!(shape.to_css(dest));
                 try!(dest.write_str(" "));
                 reference.to_css(dest)
             }
             ShapeSource::Shape(ref shape, None) => shape.to_css(dest),
--- a/servo/components/style/values/computed/image.rs
+++ b/servo/components/style/values/computed/image.rs
@@ -4,22 +4,21 @@
 
 //! CSS handling for the computed value of
 //! [`image`][image]s
 //!
 //! [image]: https://drafts.csswg.org/css-images/#image-values
 
 use cssparser::Color as CSSColor;
 use std::fmt;
+use style_traits::ToCss;
 use url::Url;
-use values::LocalToCss;
 use values::computed::{Context, Length, LengthOrPercentage, ToComputedValue};
 use values::computed::position::Position;
-use values::specified;
-use values::specified::{AngleOrCorner, SizeKeyword, UrlExtraData};
+use values::specified::{self, AngleOrCorner, SizeKeyword, UrlExtraData};
 
 
 impl ToComputedValue for specified::Image {
     type ComputedValue = Image;
 
     #[inline]
     fn to_computed_value(&self, context: &Context) -> Image {
         match *self {
@@ -68,19 +67,18 @@ impl fmt::Debug for Image {
                     GradientKind::Linear(_) => write!(f, "linear-gradient({:?})", grad),
                     GradientKind::Radial(_, _) => write!(f, "radial-gradient({:?})", grad),
                 }
             },
         }
     }
 }
 
-impl ::cssparser::ToCss for Image {
+impl ToCss for Image {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-        use values::LocalToCss;
         match *self {
             Image::Url(ref url, _) => {
                 url.to_css(dest)
             }
             Image::Gradient(ref gradient) => gradient.to_css(dest)
         }
     }
 }
@@ -93,17 +91,17 @@ pub struct Gradient {
     /// The color stops.
     pub stops: Vec<ColorStop>,
     /// True if this is a repeating gradient.
     pub repeating: bool,
     /// Gradient kind can be linear or radial.
     pub gradient_kind: GradientKind,
 }
 
-impl ::cssparser::ToCss for Gradient {
+impl ToCss for Gradient {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         if self.repeating {
             try!(dest.write_str("repeating-"));
         }
         match self.gradient_kind {
             GradientKind::Linear(angle_or_corner) => {
                 try!(dest.write_str("linear-gradient("));
                 try!(angle_or_corner.to_css(dest));
@@ -219,17 +217,17 @@ pub struct ColorStop {
     /// The color of this stop.
     pub color: CSSColor,
 
     /// The position of this stop. If not specified, this stop is placed halfway between the
     /// point that precedes it and the point that follows it per CSS-IMAGES § 3.4.
     pub position: Option<LengthOrPercentage>,
 }
 
-impl ::cssparser::ToCss for ColorStop {
+impl ToCss for ColorStop {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         try!(self.color.to_css(dest));
         if let Some(position) = self.position {
             try!(dest.write_str(" "));
             try!(position.to_css(dest));
         }
         Ok(())
     }
@@ -274,17 +272,17 @@ impl ToComputedValue for specified::Colo
 /// https://drafts.csswg.org/css-images/#valdef-radial-gradient-ending-shape
 #[derive(Clone, PartialEq)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 pub enum EndingShape {
     Circle(LengthOrKeyword),
     Ellipse(LengthOrPercentageOrKeyword),
 }
 
-impl ::cssparser::ToCss for EndingShape {
+impl ToCss for EndingShape {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         match *self {
             EndingShape::Circle(ref length) => {
                 try!(dest.write_str("circle "));
                 try!(length.to_css(dest));
             },
             EndingShape::Ellipse(ref length) => {
                 try!(dest.write_str("ellipse "));
@@ -339,17 +337,17 @@ impl ToComputedValue for specified::Grad
 /// https://drafts.csswg.org/css-images/#valdef-radial-gradient-size
 #[derive(Clone, PartialEq)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 pub enum LengthOrKeyword {
     Length(Length),
     Keyword(SizeKeyword),
 }
 
-impl ::cssparser::ToCss for LengthOrKeyword {
+impl ToCss for LengthOrKeyword {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         match *self {
             LengthOrKeyword::Length(ref length) => length.to_css(dest),
             LengthOrKeyword::Keyword(keyword) => keyword.to_css(dest),
         }
     }
 }
 
@@ -397,17 +395,17 @@ impl ToComputedValue for specified::Leng
 /// https://drafts.csswg.org/css-images/#valdef-radial-gradient-size
 #[derive(Clone, PartialEq)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 pub enum LengthOrPercentageOrKeyword {
     LengthOrPercentage(LengthOrPercentage, LengthOrPercentage),
     Keyword(SizeKeyword),
 }
 
-impl ::cssparser::ToCss for LengthOrPercentageOrKeyword {
+impl ToCss for LengthOrPercentageOrKeyword {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         match *self {
             LengthOrPercentageOrKeyword::LengthOrPercentage(ref first_len, second_len) => {
                 try!(first_len.to_css(dest));
                 try!(dest.write_str(" "));
                 second_len.to_css(dest)
             },
             LengthOrPercentageOrKeyword::Keyword(keyword) => keyword.to_css(dest),
--- a/servo/components/style/values/computed/length.rs
+++ b/servo/components/style/values/computed/length.rs
@@ -1,17 +1,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use app_units::Au;
 use ordered_float::NotNaN;
 use std::fmt;
+use style_traits::ToCss;
 use super::{Number, ToComputedValue, Context};
-use values::{CSSFloat, LocalToCss, specified};
+use values::{CSSFloat, specified};
 
 pub use cssparser::Color as CSSColor;
 pub use super::image::{EndingShape as GradientShape, Gradient, GradientKind, Image};
 pub use super::image::{LengthOrKeyword, LengthOrPercentageOrKeyword};
 pub use values::specified::{Angle, BorderStyle, Time, UrlExtraData, UrlOrNone};
 
 #[derive(Clone, PartialEq, Copy, Debug)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@@ -74,17 +75,17 @@ impl From<LengthOrPercentageOrAuto> for 
             }
             LengthOrPercentageOrAuto::Auto => {
                 None
             }
         }
     }
 }
 
-impl ::cssparser::ToCss for CalcLengthOrPercentage {
+impl ToCss for CalcLengthOrPercentage {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         match (self.length, self.percentage) {
             (None, Some(p)) => write!(dest, "{}%", p * 100.),
             (Some(l), None) => write!(dest, "{}px", Au::to_px(l)),
             (Some(l), Some(p)) => write!(dest, "calc({}px + {}%)", Au::to_px(l), p * 100.),
             _ => unreachable!()
         }
     }
@@ -187,17 +188,17 @@ impl ToComputedValue for specified::Leng
                 specified::LengthOrPercentage::Calc(
                     ToComputedValue::from_computed_value(&calc)
                 )
             }
         }
     }
 }
 
-impl ::cssparser::ToCss for LengthOrPercentage {
+impl ToCss for LengthOrPercentage {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         match *self {
             LengthOrPercentage::Length(length) => length.to_css(dest),
             LengthOrPercentage::Percentage(percentage)
             => write!(dest, "{}%", percentage * 100.),
             LengthOrPercentage::Calc(calc) => calc.to_css(dest),
         }
     }
@@ -274,17 +275,17 @@ impl ToComputedValue for specified::Leng
                 specified::LengthOrPercentageOrAuto::Calc(
                     ToComputedValue::from_computed_value(&calc)
                 )
             }
         }
     }
 }
 
-impl ::cssparser::ToCss for LengthOrPercentageOrAuto {
+impl ToCss for LengthOrPercentageOrAuto {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         match *self {
             LengthOrPercentageOrAuto::Length(length) => length.to_css(dest),
             LengthOrPercentageOrAuto::Percentage(percentage)
             => write!(dest, "{}%", percentage * 100.),
             LengthOrPercentageOrAuto::Auto => dest.write_str("auto"),
             LengthOrPercentageOrAuto::Calc(calc) => calc.to_css(dest),
         }
@@ -359,17 +360,17 @@ impl ToComputedValue for specified::Leng
                 specified::LengthOrPercentageOrAutoOrContent::Calc(
                     ToComputedValue::from_computed_value(&calc)
                 )
             }
         }
     }
 }
 
-impl ::cssparser::ToCss for LengthOrPercentageOrAutoOrContent {
+impl ToCss for LengthOrPercentageOrAutoOrContent {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         match *self {
             LengthOrPercentageOrAutoOrContent::Length(length) => length.to_css(dest),
             LengthOrPercentageOrAutoOrContent::Percentage(percentage)
             => write!(dest, "{}%", percentage * 100.),
             LengthOrPercentageOrAutoOrContent::Calc(calc) => calc.to_css(dest),
             LengthOrPercentageOrAutoOrContent::Auto => dest.write_str("auto"),
             LengthOrPercentageOrAutoOrContent::Content => dest.write_str("content")
@@ -434,17 +435,17 @@ impl ToComputedValue for specified::Leng
                 specified::LengthOrPercentageOrNone::Calc(
                     ToComputedValue::from_computed_value(&calc)
                 )
             }
         }
     }
 }
 
-impl ::cssparser::ToCss for LengthOrPercentageOrNone {
+impl ToCss for LengthOrPercentageOrNone {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         match *self {
             LengthOrPercentageOrNone::Length(length) => length.to_css(dest),
             LengthOrPercentageOrNone::Percentage(percentage) =>
                 write!(dest, "{}%", percentage * 100.),
             LengthOrPercentageOrNone::Calc(calc) => calc.to_css(dest),
             LengthOrPercentageOrNone::None => dest.write_str("none"),
         }
@@ -493,17 +494,17 @@ impl ToComputedValue for specified::Leng
             }
             LengthOrNone::None => {
                 specified::LengthOrNone::None
             }
         }
     }
 }
 
-impl ::cssparser::ToCss for LengthOrNone {
+impl ToCss for LengthOrNone {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         match *self {
             LengthOrNone::Length(length) => length.to_css(dest),
             LengthOrNone::None => dest.write_str("none"),
         }
     }
 }
 
@@ -541,17 +542,17 @@ impl ToComputedValue for specified::Leng
             LengthOrNumber::Length(len) =>
                 specified::LengthOrNumber::Length(ToComputedValue::from_computed_value(&len)),
             LengthOrNumber::Number(number) =>
                 specified::LengthOrNumber::Number(ToComputedValue::from_computed_value(&number)),
         }
     }
 }
 
-impl ::cssparser::ToCss for LengthOrNumber {
+impl ToCss for LengthOrNumber {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         match *self {
             LengthOrNumber::Length(len) => len.to_css(dest),
             LengthOrNumber::Number(number) => number.to_css(dest),
         }
     }
 }
 
--- a/servo/components/style/values/computed/mod.rs
+++ b/servo/components/style/values/computed/mod.rs
@@ -1,16 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use app_units::Au;
 use euclid::size::Size2D;
 use properties::ComputedValues;
 use std::fmt;
+use style_traits::ToCss;
 use super::{CSSFloat, specified};
 
 pub use cssparser::Color as CSSColor;
 pub use self::image::{EndingShape as GradientShape, Gradient, GradientKind, Image};
 pub use self::image::{LengthOrKeyword, LengthOrPercentageOrKeyword};
 pub use super::specified::{Angle, BorderStyle, Time, UrlExtraData, UrlOrNone};
 pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrAuto};
 pub use self::length::{LengthOrPercentageOrAutoOrContent, LengthOrPercentageOrNone, LengthOrNone};
@@ -106,16 +107,17 @@ impl ToComputedValue for specified::Leng
     }
 
     #[inline]
     fn from_computed_value(computed: &Au) -> Self {
         specified::Length::Absolute(*computed)
     }
 }
 
+
 #[derive(Debug, PartialEq, Clone, Copy)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 pub struct BorderRadiusSize(pub Size2D<LengthOrPercentage>);
 
 impl BorderRadiusSize {
     pub fn zero() -> BorderRadiusSize {
         BorderRadiusSize(Size2D::new(LengthOrPercentage::Length(Au(0)), LengthOrPercentage::Length(Au(0))))
     }
@@ -134,17 +136,17 @@ impl ToComputedValue for specified::Bord
     #[inline]
     fn from_computed_value(computed: &BorderRadiusSize) -> Self {
         let w = ToComputedValue::from_computed_value(&computed.0.width);
         let h = ToComputedValue::from_computed_value(&computed.0.height);
         specified::BorderRadiusSize(Size2D::new(w, h))
     }
 }
 
-impl ::cssparser::ToCss for BorderRadiusSize {
+impl ToCss for BorderRadiusSize {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         try!(self.0.width.to_css(dest));
         try!(dest.write_str("/"));
         self.0.height.to_css(dest)
     }
 }
 
 pub type Number = CSSFloat;
--- a/servo/components/style/values/computed/position.rs
+++ b/servo/components/style/values/computed/position.rs
@@ -2,18 +2,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! CSS handling for the computed value of
 //! [`position`][position]s
 //!
 //! [position]: https://drafts.csswg.org/css-backgrounds-3/#position
 
-use cssparser::ToCss;
 use std::fmt;
+use style_traits::ToCss;
 use values::computed::LengthOrPercentage;
 
 #[derive(Debug, Clone, PartialEq, Copy)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 pub struct Position {
     pub horizontal: LengthOrPercentage,
     pub vertical: LengthOrPercentage,
 }
--- a/servo/components/style/values/mod.rs
+++ b/servo/components/style/values/mod.rs
@@ -3,21 +3,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Common [values][values] used in CSS.
 //!
 //! [values]: https://drafts.csswg.org/css-values/
 
 pub use cssparser::RGBA;
 
-use app_units::Au;
-use cssparser::CssStringWriter;
-use std::fmt::{self, Write};
-use url::Url;
-
 macro_rules! define_numbered_css_keyword_enum {
     ($name: ident: $( $css: expr => $variant: ident = $value: expr ),+,) => {
         define_numbered_css_keyword_enum!($name: $( $css => $variant = $value ),+);
     };
     ($name: ident: $( $css: expr => $variant: ident = $value: expr ),+) => {
         #[allow(non_camel_case_types)]
         #[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Copy, RustcEncodable, Debug)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
@@ -29,62 +24,30 @@ macro_rules! define_numbered_css_keyword
             pub fn parse(input: &mut ::cssparser::Parser) -> Result<$name, ()> {
                 match_ignore_ascii_case! { try!(input.expect_ident()),
                     $( $css => Ok($name::$variant), )+
                     _ => Err(())
                 }
             }
         }
 
-        impl ::cssparser::ToCss for $name {
+        impl ToCss for $name {
             fn to_css<W>(&self, dest: &mut W) -> ::std::fmt::Result
             where W: ::std::fmt::Write {
                 match *self {
                     $( $name::$variant => dest.write_str($css) ),+
                 }
             }
         }
     }
 }
 
 pub mod computed;
 pub mod specified;
 
-/// The real ToCss trait can't be implemented for types in crates that don't
-/// depend on each other.
-pub trait LocalToCss {
-    /// Serialize `self` in CSS syntax, writing to `dest`.
-    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write;
-
-    /// Serialize `self` in CSS syntax and return a string.
-    ///
-    /// (This is a convenience wrapper for `to_css` and probably should not be overridden.)
-    #[inline]
-    fn to_css_string(&self) -> String {
-        let mut s = String::new();
-        self.to_css(&mut s).unwrap();
-        s
-    }
-}
-
-impl LocalToCss for Au {
-    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-        write!(dest, "{}px", self.to_f64_px())
-    }
-}
-
-impl LocalToCss for Url {
-    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-        try!(dest.write_str("url(\""));
-        try!(write!(CssStringWriter::new(dest), "{}", self));
-        try!(dest.write_str("\")"));
-        Ok(())
-    }
-}
-
 pub type CSSFloat = f32;
 
 pub const FONT_MEDIUM_PX: i32 = 16;
 
 pub trait HasViewportPercentage {
     fn has_viewport_percentage(&self) -> bool;
 }
 
--- a/servo/components/style/values/specified/basic_shape.rs
+++ b/servo/components/style/values/specified/basic_shape.rs
@@ -2,20 +2,21 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! CSS handling for the specified value of
 //! [`basic-shape`][basic-shape]s
 //!
 //! [basic-shape]: https://drafts.csswg.org/css-shapes/#typedef-basic-shape
 
-use cssparser::{Parser, ToCss};
+use cssparser::Parser;
 use parser::{Parse, ParserContext};
 use properties::shorthands::{parse_four_sides, serialize_four_sides};
 use std::fmt;
+use style_traits::ToCss;
 use url::Url;
 use values::computed::{ComputedValueAsSpecified, Context, ToComputedValue};
 use values::computed::basic_shape as computed_basic_shape;
 use values::specified::{BorderRadiusSize, LengthOrPercentage, Percentage};
 use values::specified::UrlExtraData;
 use values::specified::position::{Keyword, Position};
 
 /// A shape source, for some reference box
@@ -34,17 +35,16 @@ pub enum ShapeSource<T> {
 impl<T> Default for ShapeSource<T> {
     fn default() -> Self {
         ShapeSource::None
     }
 }
 
 impl<T: ToCss> ToCss for ShapeSource<T> {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-        use values::LocalToCss;
         match *self {
             ShapeSource::Url(ref url, _) => url.to_css(dest),
             ShapeSource::Shape(ref shape, Some(ref reference)) => {
                 try!(shape.to_css(dest));
                 try!(dest.write_str(" "));
                 reference.to_css(dest)
             }
             ShapeSource::Shape(ref shape, None) => shape.to_css(dest),
--- a/servo/components/style/values/specified/image.rs
+++ b/servo/components/style/values/specified/image.rs
@@ -2,37 +2,37 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! CSS handling for the specified value of
 //! [`image`][image]s
 //!
 //! [image]: https://drafts.csswg.org/css-images/#image-values
 
-use cssparser::{Parser, ToCss};
+use cssparser::Parser;
 use parser::{Parse, ParserContext};
 use std::f32::consts::PI;
 use std::fmt;
+use style_traits::ToCss;
 use url::Url;
 use values::computed::ComputedValueAsSpecified;
 use values::specified::{Angle, CSSColor, Length, LengthOrPercentage, UrlExtraData};
 use values::specified::position::Position;
 
 /// Specified values for an image according to CSS-IMAGES.
 /// https://drafts.csswg.org/css-images/#image-values
 #[derive(Clone, PartialEq, Debug)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 pub enum Image {
     Url(Url, UrlExtraData),
     Gradient(Gradient),
 }
 
 impl ToCss for Image {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-        use values::LocalToCss;
         match *self {
             Image::Url(ref url, ref _extra_data) => {
                 url.to_css(dest)
             }
             Image::Gradient(ref gradient) => gradient.to_css(dest)
         }
     }
 }
--- a/servo/components/style/values/specified/length.rs
+++ b/servo/components/style/values/specified/length.rs
@@ -1,23 +1,24 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use app_units::Au;
-use cssparser::{Parser, ToCss, Token};
+use cssparser::{Parser, Token};
 use euclid::size::Size2D;
 use parser::Parse;
 use std::ascii::AsciiExt;
 use std::cmp;
 use std::fmt;
 use std::ops::Mul;
+use style_traits::ToCss;
 use style_traits::values::specified::AllowedNumericType;
 use super::{Angle, Number, SimplifiedValueNode, SimplifiedSumNode, Time};
-use values::{CSSFloat, FONT_MEDIUM_PX, HasViewportPercentage, LocalToCss, computed};
+use values::{CSSFloat, FONT_MEDIUM_PX, HasViewportPercentage, computed};
 
 pub use super::image::{AngleOrCorner, ColorStop, EndingShape as GradientEndingShape, Gradient};
 pub use super::image::{GradientKind, HorizontalDirection, Image, LengthOrKeyword, LengthOrPercentageOrKeyword};
 pub use super::image::{SizeKeyword, VerticalDirection};
 
 #[derive(Clone, PartialEq, Copy, Debug)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 pub enum FontRelativeLength {
--- a/servo/components/style/values/specified/mod.rs
+++ b/servo/components/style/values/specified/mod.rs
@@ -1,24 +1,25 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use app_units::Au;
-use cssparser::{self, Parser, ToCss, Token};
+use cssparser::{self, Parser, Token};
 use euclid::size::Size2D;
 #[cfg(feature = "gecko")]
 use gecko_bindings::sugar::refptr::{GeckoArcPrincipal, GeckoArcURI};
 use parser::ParserContext;
 #[cfg(feature = "gecko")]
 use parser::ParserContextExtraData;
 use std::ascii::AsciiExt;
 use std::f32::consts::PI;
 use std::fmt;
 use std::ops::Mul;
+use style_traits::ToCss;
 use super::{CSSFloat, HasViewportPercentage, NoViewportPercentage};
 use super::computed::{ComputedValueAsSpecified, Context, ToComputedValue};
 use url::Url;
 
 pub use self::image::{AngleOrCorner, ColorStop, EndingShape as GradientEndingShape, Gradient};
 pub use self::image::{GradientKind, HorizontalDirection, Image, LengthOrKeyword, LengthOrPercentageOrKeyword};
 pub use self::image::{SizeKeyword, VerticalDirection};
 pub use self::length::{FontRelativeLength, ViewportPercentageLength, CharacterWidth, Length, CalcLengthOrPercentage};
@@ -550,17 +551,16 @@ pub enum UrlOrNone {
     None,
 }
 
 impl ComputedValueAsSpecified for UrlOrNone {}
 impl NoViewportPercentage for UrlOrNone {}
 
 impl ToCss for UrlOrNone {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-        use values::LocalToCss;
         match *self {
             UrlOrNone::Url(ref url, _) => {
                 url.to_css(dest)
             }
             UrlOrNone::None => {
                 try!(dest.write_str("none"));
                 Ok(())
             }
--- a/servo/components/style/values/specified/position.rs
+++ b/servo/components/style/values/specified/position.rs
@@ -2,19 +2,20 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! CSS handling for the specified value of
 //! [`position`][position]s
 //!
 //! [position]: https://drafts.csswg.org/css-backgrounds-3/#position
 
-use cssparser::{Parser, ToCss, Token};
+use cssparser::{Parser, Token};
 use parser::Parse;
 use std::fmt;
+use style_traits::ToCss;
 use values::HasViewportPercentage;
 use values::computed::{CalcLengthOrPercentage, Context};
 use values::computed::{LengthOrPercentage as ComputedLengthOrPercentage, ToComputedValue};
 use values::computed::position as computed_position;
 use values::specified::{LengthOrPercentage, Percentage};
 
 #[derive(Debug, Clone, PartialEq, Copy)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
--- a/servo/components/style/viewport.rs
+++ b/servo/components/style/viewport.rs
@@ -4,28 +4,27 @@
 
 //! The [`@viewport`][at] at-rule and [`meta`][meta] element.
 //!
 //! [at]: https://drafts.csswg.org/css-device-adapt/#atviewport-rule
 //! [meta]: https://drafts.csswg.org/css-device-adapt/#viewport-meta
 
 use app_units::Au;
 use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser, parse_important};
-use cssparser::ToCss;
 use euclid::scale_factor::ScaleFactor;
 use euclid::size::{Size2D, TypedSize2D};
 use media_queries::Device;
 use parser::{ParserContext, log_css_error};
 use properties::ComputedValues;
 use std::ascii::AsciiExt;
 use std::borrow::Cow;
 use std::fmt;
 use std::iter::Enumerate;
 use std::str::Chars;
-use style_traits::ViewportPx;
+use style_traits::{ToCss, ViewportPx};
 use style_traits::viewport::{Orientation, UserZoom, ViewportConstraints, Zoom};
 use stylesheets::{Stylesheet, Origin};
 use values::computed::{Context, ToComputedValue};
 use values::specified::{Length, LengthOrPercentageOrAuto, ViewportPercentageLength};
 
 macro_rules! declare_viewport_descriptor {
     ( $( $variant: ident($data: ident), )+ ) => {
         declare_viewport_descriptor_inner!([] [ $( $variant($data), )+ ] 0);
--- a/servo/components/style_traits/Cargo.toml
+++ b/servo/components/style_traits/Cargo.toml
@@ -17,8 +17,9 @@ servo = ["heapsize", "heapsize_derive", 
 app_units = "0.3"
 cssparser = "0.7"
 euclid = "0.10.1"
 heapsize = {version = "0.3.0", optional = true}
 heapsize_derive = {version = "0.1", optional = true}
 rustc-serialize = "0.3"
 serde = {version = "0.8", optional = true}
 serde_derive = {version = "0.8", optional = true}
+url = "1.2"
--- a/servo/components/style_traits/cursor.rs
+++ b/servo/components/style_traits/cursor.rs
@@ -1,15 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! A list of common mouse cursors per CSS3-UI § 8.1.1.
 
-use cssparser::ToCss;
+use super::ToCss;
 
 macro_rules! define_cursor {
     ($( $css: expr => $variant: ident = $value: expr, )+) => {
         #[derive(Clone, Copy, Debug, Eq, PartialEq)]
         #[cfg_attr(feature = "servo", derive(Deserialize, Serialize, HeapSizeOf))]
         #[repr(u8)]
         pub enum Cursor {
             $( $variant = $value ),+
--- a/servo/components/style_traits/lib.rs
+++ b/servo/components/style_traits/lib.rs
@@ -18,16 +18,17 @@ extern crate app_units;
 #[macro_use]
 extern crate cssparser;
 extern crate euclid;
 #[cfg(feature = "servo")] extern crate heapsize;
 #[cfg(feature = "servo")] #[macro_use] extern crate heapsize_derive;
 extern crate rustc_serialize;
 #[cfg(feature = "servo")] extern crate serde;
 #[cfg(feature = "servo")] #[macro_use] extern crate serde_derive;
+extern crate url;
 
 /// Opaque type stored in type-unsafe work queues for parallel layout.
 /// Must be transmutable to and from TNode.
 pub type UnsafeNode = (usize, usize);
 
 /// One CSS "px" in the coordinate system of the "initial viewport":
 /// http://www.w3.org/TR/css-device-adapt/#initial-viewport
 ///
@@ -56,8 +57,9 @@ pub enum PagePx {}
 //     / desktop_zoom => ViewportPx
 //       / pinch_zoom => PagePx
 
 pub mod cursor;
 #[macro_use]
 pub mod values;
 pub mod viewport;
 
+pub use values::ToCss;
--- a/servo/components/style_traits/values.rs
+++ b/servo/components/style_traits/values.rs
@@ -1,12 +1,66 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+use app_units::Au;
+use cssparser::CssStringWriter;
+use std::fmt::{self, Write};
+use url::Url;
+
+/// The real ToCss trait can't be implemented for types in crates that don't
+/// depend on each other.
+pub trait ToCss {
+    /// Serialize `self` in CSS syntax, writing to `dest`.
+    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write;
+
+    /// Serialize `self` in CSS syntax and return a string.
+    ///
+    /// (This is a convenience wrapper for `to_css` and probably should not be overridden.)
+    #[inline]
+    fn to_css_string(&self) -> String {
+        let mut s = String::new();
+        self.to_css(&mut s).unwrap();
+        s
+    }
+}
+
+impl ToCss for Au {
+    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+        write!(dest, "{}px", self.to_f64_px())
+    }
+}
+
+impl ToCss for Url {
+    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+        try!(dest.write_str("url(\""));
+        try!(write!(CssStringWriter::new(dest), "{}", self));
+        try!(dest.write_str("\")"));
+        Ok(())
+    }
+}
+
+macro_rules! impl_to_css_for_predefined_type {
+    ($name: ty) => {
+        impl<'a> ToCss for $name {
+            fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+                ::cssparser::ToCss::to_css(self, dest)
+            }
+        }
+    };
+}
+
+impl_to_css_for_predefined_type!(f32);
+impl_to_css_for_predefined_type!(i32);
+impl_to_css_for_predefined_type!(u32);
+impl_to_css_for_predefined_type!(::cssparser::Token<'a>);
+impl_to_css_for_predefined_type!(::cssparser::RGBA);
+impl_to_css_for_predefined_type!(::cssparser::Color);
+
 #[macro_export]
 macro_rules! define_css_keyword_enum {
     ($name: ident: $( $css: expr => $variant: ident ),+,) => {
         __define_css_keyword_enum__add_optional_traits!($name [ $( $css => $variant ),+ ]);
     };
     ($name: ident: $( $css: expr => $variant: ident ),+) => {
         __define_css_keyword_enum__add_optional_traits!($name [ $( $css => $variant ),+ ]);
     };
@@ -45,28 +99,27 @@ macro_rules! __define_css_keyword_enum__
             pub fn parse(input: &mut ::cssparser::Parser) -> Result<$name, ()> {
                 match_ignore_ascii_case! { try!(input.expect_ident()),
                                            $( $css => Ok($name::$variant), )+
                                            _ => Err(())
                 }
             }
         }
 
-        impl ::cssparser::ToCss for $name {
+        impl ToCss for $name {
             fn to_css<W>(&self, dest: &mut W) -> ::std::fmt::Result
                 where W: ::std::fmt::Write {
                     match *self {
                         $( $name::$variant => dest.write_str($css) ),+
                     }
                 }
         }
     }
 }
 
-
 pub mod specified {
     use app_units::Au;
 
     #[repr(u8)]
     #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
     #[derive(Clone, Copy, Debug, PartialEq, Eq)]
     pub enum AllowedNumericType {
         All,
--- a/servo/ports/cef/Cargo.lock
+++ b/servo/ports/cef/Cargo.lock
@@ -2289,16 +2289,17 @@ dependencies = [
  "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "syn"
 version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "quote 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
--- a/servo/ports/geckolib/Cargo.lock
+++ b/servo/ports/geckolib/Cargo.lock
@@ -368,16 +368,17 @@ dependencies = [
 [[package]]
 name = "style_traits"
 version = "0.0.1"
 dependencies = [
  "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "stylo_tests"
 version = "0.0.1"
 dependencies = [
  "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -1,14 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use app_units::Au;
-use cssparser::{Parser, ToCss};
+use cssparser::Parser;
 use env_logger;
 use euclid::Size2D;
 use parking_lot::RwLock;
 use std::fmt::Write;
 use std::mem::transmute;
 use std::sync::{Arc, Mutex};
 use style::arc_ptr_eq;
 use style::context::{LocalStyleContextCreationInfo, ReflowGoal, SharedStyleContext};
@@ -41,16 +41,17 @@ use style::parser::{ParserContext, Parse
 use style::properties::{CascadeFlags, ComputedValues, Importance, PropertyDeclaration};
 use style::properties::{PropertyDeclarationParseResult, PropertyDeclarationBlock};
 use style::properties::{apply_declarations, parse_one_declaration};
 use style::selector_impl::PseudoElementCascadeType;
 use style::sequential;
 use style::string_cache::Atom;
 use style::stylesheets::{Origin, Stylesheet};
 use style::timer::Timer;
+use style_traits::ToCss;
 use url::Url;
 
 /*
  * For Gecko->Servo function calls, we need to redeclare the same signature that was declared in
  * the C header in Gecko. In order to catch accidental mismatches, we run rust-bindgen against
  * those signatures as well, giving us a second declaration of all the Servo_* functions in this
  * crate. If there's a mismatch, LLVM will assert and abort, which is a rather awful thing to
  * depend on but good enough for our purposes.
--- a/servo/ports/geckolib/lib.rs
+++ b/servo/ports/geckolib/lib.rs
@@ -7,16 +7,17 @@
 #[macro_use]extern crate style;
 extern crate app_units;
 extern crate cssparser;
 extern crate env_logger;
 extern crate euclid;
 extern crate libc;
 #[macro_use] extern crate log;
 extern crate parking_lot;
+extern crate style_traits;
 extern crate url;
 
 #[allow(non_snake_case)]
 pub mod glue;
 
 // FIXME(bholley): This should probably go away once we harmonize the allocators.
 #[no_mangle]
 pub extern "C" fn je_malloc_usable_size(_: *const ::libc::c_void) -> ::libc::size_t { 0 }
--- a/servo/tests/unit/style/parsing/basic_shape.rs
+++ b/servo/tests/unit/style/parsing/basic_shape.rs
@@ -1,39 +1,40 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use parsing::parse;
 use style::parser::Parse;
 use style::values::specified::basic_shape::*;
+use style_traits::ToCss;
 
 // Ensure that basic-shape sub-functions parse as both basic shapes
 // and their individual components
 macro_rules! assert_roundtrip_basicshape {
     ($fun:expr, $input:expr, $output:expr) => {
         assert_roundtrip!($fun, $input, $output);
         assert_roundtrip!(BasicShape::parse, $input, $output);
     }
 }
 
 macro_rules! assert_border_radius_values {
     ($input:expr; $tlw:expr, $trw:expr, $brw:expr, $blw:expr ;
                   $tlh:expr, $trh:expr, $brh:expr, $blh:expr) => {
         let input = parse(BorderRadius::parse, $input)
                           .expect(&format!("Failed parsing {} as border radius",
                                   $input));
-        assert_eq!(::cssparser::ToCss::to_css_string(&input.top_left.0.width), $tlw);
-        assert_eq!(::cssparser::ToCss::to_css_string(&input.top_right.0.width), $trw);
-        assert_eq!(::cssparser::ToCss::to_css_string(&input.bottom_right.0.width), $brw);
-        assert_eq!(::cssparser::ToCss::to_css_string(&input.bottom_left.0.width), $blw);
-        assert_eq!(::cssparser::ToCss::to_css_string(&input.top_left.0.height), $tlh);
-        assert_eq!(::cssparser::ToCss::to_css_string(&input.top_right.0.height), $trh);
-        assert_eq!(::cssparser::ToCss::to_css_string(&input.bottom_right.0.height), $brh);
-        assert_eq!(::cssparser::ToCss::to_css_string(&input.bottom_left.0.height), $blh);
+        assert_eq!(::style_traits::ToCss::to_css_string(&input.top_left.0.width), $tlw);
+        assert_eq!(::style_traits::ToCss::to_css_string(&input.top_right.0.width), $trw);
+        assert_eq!(::style_traits::ToCss::to_css_string(&input.bottom_right.0.width), $brw);
+        assert_eq!(::style_traits::ToCss::to_css_string(&input.bottom_left.0.width), $blw);
+        assert_eq!(::style_traits::ToCss::to_css_string(&input.top_left.0.height), $tlh);
+        assert_eq!(::style_traits::ToCss::to_css_string(&input.top_right.0.height), $trh);
+        assert_eq!(::style_traits::ToCss::to_css_string(&input.bottom_right.0.height), $brh);
+        assert_eq!(::style_traits::ToCss::to_css_string(&input.bottom_left.0.height), $blh);
     }
 }
 
 #[test]
 fn test_inset() {
     // these are actually wrong, we should be serializing to the minimum possible result
     // the advantage of being wrong is that the roundtrip test actually suffices
     // for testing the intermediate state
--- a/servo/tests/unit/style/parsing/font.rs
+++ b/servo/tests/unit/style/parsing/font.rs
@@ -4,16 +4,17 @@
 
 use cssparser::Parser;
 use media_queries::CSSErrorReporterTest;
 use style::parser::ParserContext;
 use style::properties::longhands::font_feature_settings;
 use style::properties::longhands::font_feature_settings::computed_value;
 use style::properties::longhands::font_feature_settings::computed_value::FeatureTagValue;
 use style::stylesheets::Origin;
+use style_traits::ToCss;
 use url::Url;
 
 #[test]
 fn font_feature_settings_should_parse_properly() {
     let normal = parse_longhand!(font_feature_settings, "normal");
     let normal_computed = computed_value::T::Normal;
     assert_eq!(normal, normal_computed);
 
@@ -95,12 +96,12 @@ fn font_language_override_should_parse_p
 
     let danish = parse_longhand!(font_language_override, "\"DAN\"");
     assert_eq!(danish, SpecifiedValue::Override("DAN".to_string()));
 }
 
 #[test]
 #[should_panic]
 fn font_language_override_should_fail_on_empty_str() {
-    use style::properties::longhands::font_language_override::{self, SpecifiedValue};
+    use style::properties::longhands::font_language_override;
 
     parse_longhand!(font_language_override, "");
 }
--- a/servo/tests/unit/style/parsing/image.rs
+++ b/servo/tests/unit/style/parsing/image.rs
@@ -2,16 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use cssparser::Parser;
 use media_queries::CSSErrorReporterTest;
 use style::parser::ParserContext;
 use style::stylesheets::Origin;
 use style::values::specified::image::*;
+use style_traits::ToCss;
 use url::Url;
 
 #[test]
 fn test_linear_gradient() {
     // Parsing from the right
     assert_roundtrip_with_context!(Image::parse, "linear-gradient(to left, red, green)",
                                                  "linear-gradient(4.712389rad, red, green)");
 
--- a/servo/tests/unit/style/parsing/mod.rs
+++ b/servo/tests/unit/style/parsing/mod.rs
@@ -16,43 +16,43 @@ fn parse<T, F: Fn(&mut Parser) -> Result
 // is preserved in the panic
 macro_rules! assert_roundtrip {
     ($fun:expr, $string:expr) => {
         assert_roundtrip!($fun, $string, $string);
     };
     ($fun:expr, $input:expr, $output:expr) => {
         let parsed = $crate::parsing::parse($fun, $input)
                         .expect(&format!("Failed to parse {}", $input));
-        let serialized = ::cssparser::ToCss::to_css_string(&parsed);
+        let serialized = ToCss::to_css_string(&parsed);
         assert_eq!(serialized, $output);
 
         let re_parsed = $crate::parsing::parse($fun, &serialized)
                         .expect(&format!("Failed to parse serialization {}", $input));
-        let re_serialized = ::cssparser::ToCss::to_css_string(&re_parsed);
+        let re_serialized = ToCss::to_css_string(&re_parsed);
         assert_eq!(serialized, re_serialized);
     }
 }
 
 macro_rules! assert_roundtrip_with_context {
     ($fun:expr, $string:expr) => {
         assert_roundtrip_with_context!($fun, $string, $string);
     };
     ($fun:expr,$input:expr, $output:expr) => {
         let url = Url::parse("http://localhost").unwrap();
         let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
         let mut parser = Parser::new($input);
         let parsed = $fun(&context, &mut parser)
                      .expect(&format!("Failed to parse {}", $input));
-        let serialized = ::cssparser::ToCss::to_css_string(&parsed);
+        let serialized = ToCss::to_css_string(&parsed);
         assert_eq!(serialized, $output);
 
         let mut parser = Parser::new(&serialized);
         let re_parsed = $fun(&context, &mut parser)
                         .expect(&format!("Failed to parse {}", $input));
-        let re_serialized = ::cssparser::ToCss::to_css_string(&re_parsed);
+        let re_serialized = ToCss::to_css_string(&re_parsed);
         assert_eq!(serialized, re_serialized);
     }
 }
 
 
 macro_rules! parse_longhand {
     ($name:ident, $s:expr) => {{
         let url = Url::parse("http://localhost").unwrap();
--- a/servo/tests/unit/style/parsing/position.rs
+++ b/servo/tests/unit/style/parsing/position.rs
@@ -1,14 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use parsing::parse;
 use style::values::specified::position::*;
+use style_traits::ToCss;
 
 #[test]
 fn test_position() {
     // Serialization is not actually specced
     // though these are the values expected by basic-shape
     // https://github.com/w3c/csswg-drafts/issues/368
     assert_roundtrip!(Position::parse, "center", "center center");
     assert_roundtrip!(Position::parse, "top left", "left top");
--- a/servo/tests/unit/style/parsing/selectors.rs
+++ b/servo/tests/unit/style/parsing/selectors.rs
@@ -1,13 +1,13 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-use cssparser::Parser;
+use cssparser::{Parser, ToCss};
 use selectors::parser::{Selector, ParserContext, parse_selector_list};
 use style::selector_impl::TheSelectorImpl;
 
 fn parse(input: &mut Parser) -> Result<Selector<TheSelectorImpl>, ()> {
     let mut context = ParserContext::new();
     context.in_user_agent_stylesheet = true;
     context.namespace_prefixes.insert("svg".into(), ns!(svg));
     parse_selector_list(&context, input).map(|mut vec| vec.pop().unwrap())
--- a/servo/tests/unit/style/properties/serialization.rs
+++ b/servo/tests/unit/style/properties/serialization.rs
@@ -1,21 +1,21 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-pub use cssparser::ToCss;
 pub use std::sync::Arc;
 pub use style::computed_values::display::T::inline_block;
 pub use style::properties::{DeclaredValue, PropertyDeclaration, PropertyDeclarationBlock, Importance};
 pub use style::values::specified::{BorderStyle, BorderWidth, CSSColor, Length};
 pub use style::values::specified::{LengthOrPercentage, LengthOrPercentageOrAuto, LengthOrPercentageOrAutoOrContent};
 pub use style::properties::longhands::outline_color::computed_value::T as ComputedColor;
 pub use style::values::RGBA;
 pub use style::values::specified::UrlExtraData;
+pub use style_traits::ToCss;
 pub use url::Url;
 
 #[test]
 fn property_declaration_block_should_serialize_correctly() {
     use style::properties::longhands::overflow_x::computed_value::T as OverflowXValue;
     use style::properties::longhands::overflow_y::computed_value::T as OverflowYContainer;
 
     let declarations = vec![
--- a/servo/tests/unit/stylo/lib.rs
+++ b/servo/tests/unit/stylo/lib.rs
@@ -6,14 +6,15 @@ extern crate app_units;
 extern crate cssparser;
 extern crate env_logger;
 extern crate euclid;
 extern crate geckoservo;
 extern crate libc;
 #[macro_use] extern crate log;
 extern crate parking_lot;
 extern crate style;
+extern crate style_traits;
 extern crate url;
 
 mod sanity_checks;
 
 mod servo_function_signatures;