Subject: [PATCH] Support completion of attribute values in CSS mode

From: Simen Heggestøyl <[email-masked]>
Date: Sun, 06 Mar 2016 14:53:52 +0100

Hello!

I've finally gotten around to implement property value completion in
CSS mode. I've been using the attached patch privately for some weeks
now, and it seems to me that it works well.

The code has taken much inspiration from company-css.el, but there are
some differences:

- Completion lists for many new properties have been added, and a few
  have been removed (most of them from the obsoleted marquee
  module [1]).

- I've manually updated all completion lists according to the CSS spec
  and fixed some bugs in the existing lists along the way. In general
  I've tried to stay as close as possible to the grammar described in
  the CSS spec wrt. names and order of the values and classes.

- The new `css--property-values' function is very similar to
  `company-css-property-values', but it has been updated to support
  following completion candidates further from the value class
  completion lists.

- Completion a function name will no longer put commas between the
  parenthesis. My reason for this is that many CSS functions take a
  variable number of arguments. For instance, the `translate' function
  is completed by company-css to `translate(,)', but `translate' can
  take only one argument too, so the completion is misleading. Also,
  there are functions that support an arbitrary number of
  arguments. Instead of trying to support this, I've made every
  function name complete to just `function()'. I think having ElDoc
  support for CSS functions would be good for making it easier to
  remember which arguments functions take.

- `inherit' has been added as a completion candidate for every
  property.

Please have a look at the patch and tell me what you think!

-- Simen

[1] https://www.w3.org/TR/css3-marquee/
>From cff60501026539692491a5f422b7dcb415402b70 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simen=20Heggest=C3=B8yl?= <[email-masked]>
Date: Sat, 13 Feb 2016 22:18:42 +0100
Subject: [PATCH] Support completion of attribute values in CSS mode

* lisp/textmodes/css-mode.el (css-property-alist): New defconst
holding CSS identifiers and the values they can have.
(css-property-ids): Compute dynamically from `css-property-alist'.
(css-value-class-alist): New defconst holding property value classes
and their values.
(css--property-value-cache): New variable providing a cache for
`css--property-values'.
(css--property-values): New function for computing a list of possible
values for a CSS property.
(css--complete-property-value): New function for completing a property
value.
(css-completion-at-point): Add support for completing property values.
---
 etc/NEWS                   |   6 +
 lisp/textmodes/css-mode.el | 513 ++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 445 insertions(+), 74 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 92d69d2..d2486da 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -127,6 +127,12 @@ different group ID.
 ---
 ** `auto-revert-use-notify' is set back to t in `global-auto-revert-mode'.
 
+** CSS mode
+
+---
+*** Support for completing attribute values using the `completion-at-point'
+command.
+
 
 * New Modes and Packages in Emacs 25.2
 
diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el
index 93a8dce..2bb3dd8 100644
--- a/lisp/textmodes/css-mode.el
+++ b/lisp/textmodes/css-mode.el
@@ -29,7 +29,6 @@
 
 ;; - electric ; and }
 ;; - filling code with auto-fill-mode
-;; - attribute value completion
 ;; - fix font-lock errors with multi-line selectors
 
 ;;; Code:
@@ -74,124 +73,455 @@ css-media-ids
     "visual")
   "Identifiers for types of media.")
 
-(defconst css-property-ids
-  '(;; CSS 2.1 properties (http://www.w3.org/TR/CSS21/propidx.html).
-    ;;
-    ;; Properties duplicated by any of the CSS3 modules below have
-    ;; been removed.
-    "azimuth" "border-collapse" "border-spacing" "bottom"
-    "caption-side" "clear" "clip" "content" "counter-increment"
-    "counter-reset" "cue" "cue-after" "cue-before" "direction" "display"
-    "elevation" "empty-cells" "float" "height" "left" "line-height"
-    "list-style" "list-style-image" "list-style-position"
-    "list-style-type" "margin" "margin-bottom" "margin-left"
-    "margin-right" "margin-top" "max-height" "max-width" "min-height"
-    "min-width" "padding" "padding-bottom" "padding-left"
-    "padding-right" "padding-top" "page-break-after"
-    "page-break-before" "page-break-inside" "pause" "pause-after"
-    "pause-before" "pitch" "pitch-range" "play-during" "position"
-    "quotes" "richness" "right" "speak" "speak-header" "speak-numeral"
-    "speak-punctuation" "speech-rate" "stress" "table-layout" "top"
-    "unicode-bidi" "vertical-align" "visibility" "voice-family" "volume"
-    "width" "z-index"
+(defconst css-property-alist
+  ;; CSS 2.1 properties (http://www.w3.org/TR/CSS21/propidx.html).
+  ;;
+  ;; Properties duplicated by any of the CSS3 modules below have been
+  ;; removed.
+  '(("azimuth" angle "left-side" "far-left" "left" "center-left"
+     "center" "center-right" "right" "far-right" "right-side" "behind"
+     "leftwards" "rightwards")
+    ("border-collapse" "collapse" "separate")
+    ("border-spacing" length)
+    ("bottom" length percentage "auto")
+    ("caption-side" "top" "bottom")
+    ("clear" "none" "left" "right" "both")
+    ("clip" shape "auto")
+    ("content" "normal" "none" string uri counter "attr()"
+     "open-quote" "close-quote" "no-open-quote" "no-close-quote")
+    ("counter-increment" identifier integer "none")
+    ("counter-reset" identifier integer "none")
+    ("cue" cue-before cue-after)
+    ("cue-after" uri "none")
+    ("cue-before" uri "none")
+    ("direction" "ltr" "rtl")
+    ("display" "inline" "block" "list-item" "inline-block" "table"
+     "inline-table" "table-row-group" "table-header-group"
+     "table-footer-group" "table-row" "table-column-group"
+     "table-column" "table-cell" "table-caption" "none"
+     ;; CSS Flexible Box Layout Module Level 1
+     ;; (https://www.w3.org/TR/css3-flexbox/#valdef-display-flex)
+     "flex" "inline-flex")
+    ("elevation" angle "below" "level" "above" "higher" "lower")
+    ("empty-cells" "show" "hide")
+    ("float" "left" "right" "none")
+    ("height" length percentage "auto")
+    ("left" length percentage "auto")
+    ("line-height" "normal" number length percentage)
+    ("list-style" list-style-type list-style-position
+     list-style-image)
+    ("list-style-image" uri "none")
+    ("list-style-position" "inside" "outside")
+    ("list-style-type" "disc" "circle" "square" "decimal"
+     "decimal-leading-zero" "lower-roman" "upper-roman" "lower-greek"
+     "lower-latin" "upper-latin" "armenian" "georgian" "lower-alpha"
+     "upper-alpha" "none")
+    ("margin" margin-width)
+    ("margin-bottom" margin-width)
+    ("margin-left" margin-width)
+    ("margin-right" margin-width)
+    ("margin-top" margin-width)
+    ("max-height" length percentage "none")
+    ("max-width" length percentage "none")
+    ("min-height" length percentage)
+    ("min-width" length percentage)
+    ("padding" padding-width)
+    ("padding-bottom" padding-width)
+    ("padding-left" padding-width)
+    ("padding-right" padding-width)
+    ("padding-top" padding-width)
+    ("page-break-after" "auto" "always" "avoid" "left" "right")
+    ("page-break-before" "auto" "always" "avoid" "left" "right")
+    ("page-break-inside" "avoid" "auto")
+    ("pause" time percentage)
+    ("pause-after" time percentage)
+    ("pause-before" time percentage)
+    ("pitch" frequency "x-low" "low" "medium" "high" "x-high")
+    ("pitch-range" number)
+    ("play-during" uri "mix" "repeat" "auto" "none")
+    ("position" "static" "relative" "absolute" "fixed")
+    ("quotes" string "none")
+    ("richness" number)
+    ("right" length percentage "auto")
+    ("speak" "normal" "none" "spell-out")
+    ("speak-header" "once" "always")
+    ("speak-numeral" "digits" "continuous")
+    ("speak-punctuation" "code" "none")
+    ("speech-rate" number "x-slow" "slow" "medium" "fast" "x-fast"
+     "faster" "slower")
+    ("stress" number)
+    ("table-layout" "auto" "fixed")
+    ("top" length percentage "auto")
+    ("unicode-bidi" "normal" "embed" "bidi-override")
+    ("vertical-align" "baseline" "sub" "super" "top" "text-top"
+     "middle" "bottom" "text-bottom" percentage length)
+    ("visibility" "visible" "hidden" "collapse")
+    ("voice-family" specific-voice generic-voice specific-voice
+     generic-voice)
+    ("volume" number percentage "silent" "x-soft" "soft" "medium"
+     "loud" "x-loud")
+    ("width" length percentage "auto")
+    ("z-index" "auto" integer)
 
     ;; CSS Animations
     ;; (http://www.w3.org/TR/css3-animations/#property-index)
-    "animation" "animation-delay" "animation-direction"
-    "animation-duration" "animation-fill-mode"
-    "animation-iteration-count" "animation-name"
-    "animation-play-state" "animation-timing-function"
+    ("animation" single-animation-name time single-timing-function
+     single-animation-iteration-count single-animation-direction
+     single-animation-fill-mode single-animation-play-state)
+    ("animation-delay" time)
+    ("animation-direction" single-animation-direction)
+    ("animation-duration" time)
+    ("animation-fill-mode" single-animation-fill-mode)
+    ("animation-iteration-count" single-animation-iteration-count)
+    ("animation-name" single-animation-name)
+    ("animation-play-state" single-animation-play-state)
+    ("animation-timing-function" single-timing-function)
 
     ;; CSS Backgrounds and Borders Module Level 3
     ;; (http://www.w3.org/TR/css3-background/#property-index)
-    "background" "background-attachment" "background-clip"
-    "background-color" "background-image" "background-origin"
-    "background-position" "background-repeat" "background-size"
-    "border" "border-bottom" "border-bottom-color"
-    "border-bottom-left-radius" "border-bottom-right-radius"
-    "border-bottom-style" "border-bottom-width" "border-color"
-    "border-image" "border-image-outset" "border-image-repeat"
-    "border-image-slice" "border-image-source" "border-image-width"
-    "border-left" "border-left-color" "border-left-style"
-    "border-left-width" "border-radius" "border-right"
-    "border-right-color" "border-right-style" "border-right-width"
-    "border-style" "border-top" "border-top-color"
-    "border-top-left-radius" "border-top-right-radius"
-    "border-top-style" "border-top-width" "border-width" "box-shadow"
+    ("background" bg-layer)
+    ("background-attachment" attachment)
+    ("background-clip" box)
+    ("background-color" color)
+    ("background-image" bg-image)
+    ("background-origin" box)
+    ("background-position" position)
+    ("background-repeat" repeat-style)
+    ("background-size" bg-size)
+    ("border" line-width line-style color)
+    ("border-bottom" line-width line-style color)
+    ("border-bottom-color" color)
+    ("border-bottom-left-radius" length percentage)
+    ("border-bottom-right-radius" length percentage)
+    ("border-bottom-style" line-style)
+    ("border-bottom-width" line-width)
+    ("border-color" color)
+    ("border-image" border-image-source border-image-slice
+     border-image-width border-image-outset border-image-repeat)
+    ("border-image-outset" length number)
+    ("border-image-repeat" "stretch" "repeat" "round" "space")
+    ("border-image-slice" number percentage "fill")
+    ("border-image-source" "none" image)
+    ("border-image-width" length percentage number "auto")
+    ("border-left" line-width line-style color)
+    ("border-left-color" color)
+    ("border-left-style" line-style)
+    ("border-left-width" line-width)
+    ("border-radius" length percentage "/")
+    ("border-right" line-width line-style color)
+    ("border-right-color" color)
+    ("border-right-style" line-style)
+    ("border-right-width" line-width)
+    ("border-style" line-style)
+    ("border-top" line-width line-style color)
+    ("border-top-color" color)
+    ("border-top-left-radius" length percentage)
+    ("border-top-right-radius" length percentage)
+    ("border-top-style" line-style)
+    ("border-top-width" line-width)
+    ("border-width" line-width)
+    ("box-shadow" "none" shadow)
 
     ;; CSS Basic User Interface Module Level 3 (CSS3 UI)
     ;; (http://www.w3.org/TR/css3-ui/#property-index)
-    "box-sizing" "caret-color" "cursor" "nav-down" "nav-left"
-    "nav-right" "nav-up" "outline" "outline-color" "outline-offset"
-    "outline-style" "outline-width" "resize" "text-overflow"
+    ("box-sizing" "content-box" "border-box")
+    ("caret-color" "auto" color)
+    ("cursor" uri x y "auto" "default" "none" "context-menu" "help"
+     "pointer" "progress" "wait" "cell" "crosshair" "text"
+     "vertical-text" "alias" "copy" "move" "no-drop" "not-allowed"
+     "grab" "grabbing" "e-resize" "n-resize" "ne-resize" "nw-resize"
+     "s-resize" "se-resize" "sw-resize" "w-resize" "ew-resize"
+     "ns-resize" "nesw-resize" "nwse-resize" "col-resize" "row-resize"
+     "all-scroll" "zoom-in" "zoom-out")
+    ("nav-down" "auto" id "current" "root" target-name)
+    ("nav-left" "auto" id "current" "root" target-name)
+    ("nav-right" "auto" id "current" "root" target-name)
+    ("nav-up" "auto" id "current" "root" target-name)
+    ("outline" outline-color outline-style outline-width)
+    ("outline-color" color "invert")
+    ("outline-offset" length)
+    ("outline-style" "auto" border-style)
+    ("outline-width" border-width)
+    ("resize" "none" "both" "horizontal" "vertical")
+    ("text-overflow" "clip" "ellipsis" string)
 
     ;; CSS Color Module Level 3
     ;; (http://www.w3.org/TR/css3-color/#property)
-    "color" "opacity"
+    ("color" color)
+    ("opacity" alphavalue)
 
     ;; CSS Flexible Box Layout Module Level 1
     ;; (http://www.w3.org/TR/css-flexbox-1/#property-index)
-    "align-content" "align-items" "align-self" "flex" "flex-basis"
-    "flex-direction" "flex-flow" "flex-grow" "flex-shrink" "flex-wrap"
-    "justify-content" "order"
+    ("align-content" "flex-start" "flex-end" "center" "space-between"
+     "space-around" "stretch")
+    ("align-items" "flex-start" "flex-end" "center" "baseline"
+     "stretch")
+    ("align-self" "auto" "flex-start" "flex-end" "center" "baseline"
+     "stretch")
+    ("flex" "none" flex-grow flex-shrink flex-basis)
+    ("flex-basis" "auto" "content" width)
+    ("flex-direction" "row" "row-reverse" "column" "column-reverse")
+    ("flex-flow" flex-direction flex-wrap)
+    ("flex-grow" number)
+    ("flex-shrink" number)
+    ("flex-wrap" "nowrap" "wrap" "wrap-reverse")
+    ("justify-content" "flex-start" "flex-end" "center"
+     "space-between" "space-around")
+    ("order" integer)
 
     ;; CSS Fonts Module Level 3
     ;; (http://www.w3.org/TR/css3-fonts/#property-index)
-    "font" "font-family" "font-feature-settings" "font-kerning"
-    "font-language-override" "font-size" "font-size-adjust"
-    "font-stretch" "font-style" "font-synthesis" "font-variant"
-    "font-variant-alternates" "font-variant-caps"
-    "font-variant-east-asian" "font-variant-ligatures"
-    "font-variant-numeric" "font-variant-position" "font-weight"
+    ("font" font-style font-variant-css21 font-weight font-stretch
+     font-size "/" line-height font-family "caption" "icon" "menu"
+     "message-box" "small-caption" "status-bar")
+    ("font-family" family-name generic-family)
+    ("font-feature-settings" "normal" feature-tag-value)
+    ("font-kerning" "auto" "normal" "none")
+    ("font-language-override" "normal" string)
+    ("font-size" absolute-size relative-size length percentage)
+    ("font-size-adjust" "none" number)
+    ("font-stretch" "normal" "ultra-condensed" "extra-condensed"
+     "condensed" "semi-condensed" "semi-expanded" "expanded"
+     "extra-expanded" "ultra-expanded")
+    ("font-style" "normal" "italic" "oblique")
+    ("font-synthesis" "none" "weight" "style")
+    ("font-variant" "normal" "none" common-lig-values
+     discretionary-lig-values historical-lig-values
+     contextual-alt-values "stylistic()" "historical-forms"
+     "styleset()" "character-variant()" "swash()" "ornaments()"
+     "annotation()" "small-caps" "all-small-caps" "petite-caps"
+     "all-petite-caps" "unicase" "titling-caps" numeric-figure-values
+     numeric-spacing-values numeric-fraction-values "ordinal"
+     "slashed-zero" east-asian-variant-values east-asian-width-values
+     "ruby")
+    ("font-variant-alternates" "normal" "stylistic()"
+     "historical-forms" "styleset()" "character-variant()" "swash()"
+     "ornaments()" "annotation()")
+    ("font-variant-caps" "normal" "small-caps" "all-small-caps"
+     "petite-caps" "all-petite-caps" "unicase" "titling-caps")
+    ("font-variant-east-asian" "normal" east-asian-variant-values
+     east-asian-width-values "ruby")
+    ("font-variant-ligatures" "normal" "none" common-lig-values
+     discretionary-lig-values historical-lig-values
+     contextual-alt-values)
+    ("font-variant-numeric" "normal" numeric-figure-values
+     numeric-spacing-values numeric-fraction-values "ordinal"
+     "slashed-zero")
+    ("font-variant-position" "normal" "sub" "super")
+    ("font-weight" "normal" "bold" "bolder" "lighter" "100" "200"
+     "300" "400" "500" "600" "700" "800" "900")
 
     ;; CSS Fragmentation Module Level 3
     ;; (https://www.w3.org/TR/css-break-3/#property-index)
-    "box-decoration-break" "break-after" "break-before" "break-inside"
-    "orphans" "widows"
+    ("box-decoration-break" "slice" "clone")
+    ("break-after" "auto" "avoid" "avoid-page" "page" "left" "right"
+     "recto" "verso" "avoid-column" "column" "avoid-region" "region")
+    ("break-before" "auto" "avoid" "avoid-page" "page" "left" "right"
+     "recto" "verso" "avoid-column" "column" "avoid-region" "region")
+    ("break-inside" "auto" "avoid" "avoid-page" "avoid-column"
+     "avoid-region")
+    ("orphans" integer)
+    ("widows" integer)
 
     ;; CSS Multi-column Layout Module
     ;; (https://www.w3.org/TR/css3-multicol/#property-index)
     ;; "break-after", "break-before", and "break-inside" are left out
     ;; below, because they're already included in CSS Fragmentation
     ;; Module Level 3.
-    "column-count" "column-fill" "column-gap" "column-rule"
-    "column-rule-color" "column-rule-style" "column-rule-width"
-    "column-span" "column-width" "columns"
+    ("column-count" integer "auto")
+    ("column-fill" "auto" "balance")
+    ("column-gap" length "normal")
+    ("column-rule" column-rule-width column-rule-style
+     column-rule-color "transparent")
+    ("column-rule-color" color)
+    ("column-rule-style" border-style)
+    ("column-rule-width" border-width)
+    ("column-span" "none" "all")
+    ("column-width" length "auto")
+    ("columns" column-width column-count)
 
     ;; CSS Overflow Module Level 3
     ;; (http://www.w3.org/TR/css-overflow-3/#property-index)
-    "max-lines" "overflow" "overflow-x" "overflow-y"
+    ("max-lines" "none" integer)
+    ("overflow" "visible" "hidden" "scroll" "auto" "paged-x" "paged-y"
+     "paged-x-controls" "paged-y-controls" "fragments")
+    ("overflow-x" "visible" "hidden" "scroll" "auto" "paged-x"
+     "paged-y" "paged-x-controls" "paged-y-controls" "fragments")
+    ("overflow-y" "visible" "hidden" "scroll" "auto" "paged-x"
+     "paged-y" "paged-x-controls" "paged-y-controls" "fragments")
 
     ;; CSS Text Decoration Module Level 3
     ;; (http://dev.w3.org/csswg/css-text-decor-3/#property-index)
-    "text-decoration" "text-decoration-color" "text-decoration-line"
-    "text-decoration-skip" "text-decoration-style" "text-emphasis"
-    "text-emphasis-color" "text-emphasis-position" "text-emphasis-style"
-    "text-shadow" "text-underline-position"
+    ("text-decoration" text-decoration-line text-decoration-style
+     text-decoration-color)
+    ("text-decoration-color" color)
+    ("text-decoration-line" "none" "underline" "overline"
+     "line-through" "blink")
+    ("text-decoration-skip" "none" "objects" "spaces" "ink" "edges"
+     "box-decoration")
+    ("text-decoration-style" "solid" "double" "dotted" "dashed"
+     "wavy")
+    ("text-emphasis" text-emphasis-style text-emphasis-color)
+    ("text-emphasis-color" color)
+    ("text-emphasis-position" "over" "under" "right" "left")
+    ("text-emphasis-style" "none" "filled" "open" "dot" "circle"
+     "double-circle" "triangle" "sesame" string)
+    ("text-shadow" "none" length color)
+    ("text-underline-position" "auto" "under" "left" "right")
 
     ;; CSS Text Module Level 3
     ;; (http://www.w3.org/TR/css3-text/#property-index)
-    "hanging-punctuation" "hyphens" "letter-spacing" "line-break"
-    "overflow-wrap" "tab-size" "text-align" "text-align-last"
-    "text-indent" "text-justify" "text-transform" "white-space"
-    "word-break" "word-spacing" "word-wrap"
+    ("hanging-punctuation" "none" "first" "force-end" "allow-end"
+     "last")
+    ("hyphens" "none" "manual" "auto")
+    ("letter-spacing" "normal" length)
+    ("line-break" "auto" "loose" "normal" "strict")
+    ("overflow-wrap" "normal" "break-word")
+    ("tab-size" integer length)
+    ("text-align" "start" "end" "left" "right" "center" "justify"
+     "match-parent")
+    ("text-align-last" "auto" "start" "end" "left" "right" "center"
+     "justify")
+    ("text-indent" length percentage)
+    ("text-justify" "auto" "none" "inter-word" "distribute")
+    ("text-transform" "none" "capitalize" "uppercase" "lowercase"
+     "full-width")
+    ("white-space" "normal" "pre" "nowrap" "pre-wrap" "pre-line")
+    ("word-break" "normal" "keep-all" "break-all")
+    ("word-spacing" "normal" length percentage)
+    ("word-wrap" "normal" "break-word")
 
     ;; CSS Transforms Module Level 1
     ;; (http://www.w3.org/TR/css3-2d-transforms/#property-index)
-    "backface-visibility" "perspective" "perspective-origin"
-    "transform" "transform-origin" "transform-style"
+    ("backface-visibility" "visible" "hidden")
+    ("perspective" "none" length)
+    ("perspective-origin" "left" "center" "right" "top" "bottom"
+     percentage length)
+    ("transform" "none" transform-list)
+    ("transform-origin" "left" "center" "right" "top" "bottom"
+     percentage length)
+    ("transform-style" "flat" "preserve-3d")
 
     ;; CSS Transitions
     ;; (http://www.w3.org/TR/css3-transitions/#property-index)
-    "transition" "transition-delay" "transition-duration"
-    "transition-property" "transition-timing-function"
+    ("transition" single-transition)
+    ("transition-delay" time)
+    ("transition-duration" time)
+    ("transition-property" "none" single-transition-property "all")
+    ("transition-timing-function" single-transition-timing-function)
 
     ;; Filter Effects Module Level 1
     ;; (http://www.w3.org/TR/filter-effects/#property-index)
-    "color-interpolation-filters" "filter" "flood-color"
-    "flood-opacity" "lighting-color")
+    ("color-interpolation-filters" "auto" "sRGB" "linearRGB")
+    ("filter" "none" filter-function-list)
+    ("flood-color" color)
+    ("flood-opacity" number percentage)
+    ("lighting-color" color))
+  "Identifiers for properties and their possible values.
+The CAR of each entry is the name of a property, while the CDR is
+a list of possible values for that property. A string value
+represents a literal value, while a symbol must be looked up in
+`css-property-alist' and `css-value-class-alist' to find further
+possible values. Some symbols, such as `number' or `identifier',
+don't produce any further value candidates, since that list would
+be infinite.")
+
+(defconst css-property-ids
+  (mapcar #'car css-property-alist)
   "Identifiers for properties.")
 
+(defconst css-value-class-alist
+  '(("absolute-size" "xx-small" "x-small" "small" "medium" "large"
+     "x-large" "xx-large")
+    ("alphavalue" number)
+    ("attachment" "scroll" "fixed" "local")
+    ("bg-image" image "none")
+    ("bg-layer" bg-image position "/" repeat-style attachment box
+     background-color)
+    ("bg-size" length percentage "auto" "cover" "contain")
+    ("box" "border-box" "padding-box" "content-box")
+    ("color" "aqua" "black" "blue" "fuchsia" "gray" "green" "lime"
+     "maroon" "navy" "olive" "orange" "purple" "red" "silver" "teal"
+     "white" "yellow" "transparent")
+    ("common-lig-values" "common-ligatures" "no-common-ligatures")
+    ("contextual-alt-values" "contextual" "no-contextual")
+    ("counter" "counter()" "counters()")
+    ("discretionary-lig-values" "discretionary-ligatures"
+     "no-discretionary-ligatures")
+    ("east-asian-variant-values" "jis78" "jis83" "jis90" "jis04"
+     "simplified" "traditional")
+    ("east-asian-width-values" "full-width" "proportional-width")
+    ("family-name" "Courier" "Helvetica" "Times")
+    ("feature-tag-value" string integer "on" "off")
+    ("filter-function" "blur()" "brightness()" "contrast()"
+     "drop-shadow()" "grayscale()" "hue-rotate()" "invert()"
+     "opacity()" "sepia()" "saturate()")
+    ("filter-function-list" filter-function uri)
+    ("font-variant-css21" "normal" "small-caps")
+    ("generic-family" "serif" "sans-serif" "cursive" "fantasy"
+     "monospace")
+    ("generic-voice" "male" "female" "child")
+    ("gradient" linear-gradient radial-gradient
+     repeating-linear-gradient repeating-radial-gradient)
+    ("historical-lig-values" "historical-ligatures"
+     "no-historical-ligatures")
+    ("image" uri image-list element-reference gradient)
+    ("image-list" "image()")
+    ("length" number)
+    ("line-height" "normal" number length percentage)
+    ("line-style" "none" "hidden" "dotted" "dashed" "solid" "double"
+     "groove" "ridge" "inset" "outset")
+    ("line-width" length "thin" "medium" "thick")
+    ("linear-gradient" "linear-gradient()")
+    ("margin-width" "auto" length percentage)
+    ("numeric-figure-values" "lining-nums" "oldstyle-nums")
+    ("numeric-fraction-values" "diagonal-fractions"
+     "stacked-fractions")
+    ("numeric-spacing-values" "proportional-nums" "tabular-nums")
+    ("padding-width" length percentage)
+    ("radial-gradient" "radial-gradient()")
+    ("relative-size" "larger" "smaller")
+    ("repeat-style" "repeat-x" "repeat-y" "repeat" "space" "round"
+     "no-repeat")
+    ("repeating-linear-gradient" "repeating-linear-gradient()")
+    ("repeating-radial-gradient" "repeating-radial-gradient()")
+    ("shadow" "inset" length color)
+    ("shape" "rect()")
+    ("single-animation-direction" "normal" "reverse" "alternate"
+     "alternate-reverse")
+    ("single-animation-fill-mode" "none" "forwards" "backwards"
+     "both")
+    ("single-animation-iteration-count" "infinite" number)
+    ("single-animation-name" "none" identifier)
+    ("single-animation-play-state" "running" "paused")
+    ("single-timing-function" single-transition-timing-function)
+    ("single-transition" "none" single-transition-property time
+     single-transition-timing-function)
+    ("single-transition-property" "all" identifier)
+    ("single-transition-timing-function" "ease" "linear" "ease-in"
+     "ease-out" "ease-in-out" "step-start" "step-end" "steps()"
+     "cubic-bezier()")
+    ("specific-voice" identifier)
+    ("target-name" string)
+    ("transform-list" "matrix()" "translate()" "translateX()"
+     "translateY()" "scale()" "scaleX()" "scaleY()" "rotate()"
+     "skew()" "skewX()" "skewY()" "matrix3d()" "translate3d()"
+     "translateZ()" "scale3d()" "scaleZ()" "rotate3d()" "rotateX()"
+     "rotateY()" "rotateZ()" "perspective()")
+    ("uri" "url()")
+    ("width" length percentage "auto")
+    ("x" number)
+    ("y" number))
+  "Property value classes and their values.
+The format is equal to that of `css-property-alist', except that
+the CARs aren't actual CSS properties, but rather a name for a
+class of values.
+
+The following classes have been left out above because they
+cannot be completed sensibly: `angle', `element-reference',
+`frequency', `id', `identifier', `integer', `number',
+`percentage', `string', and `time'.")
+
 (defcustom css-electric-keys '(?\} ?\;) ;; '()
   "Self inserting keys which should trigger re-indentation."
   :version "22.2"
@@ -410,11 +740,46 @@ css--complete-at-rule
       (when (eq (char-before) ?\@)
         (list (point) pos css-at-ids)))))
 
+(defvar css--property-value-cache
+  (make-hash-table :test 'equal :size (+ (length css-property-alist)
+                                         (length css-value-class-alist)))
+  "Cache of previously completed property values.")
+
+(defun css--property-values (property)
+  "Return value completion candidates for PROPERTY."
+  (or (gethash property css--property-value-cache)
+      (let (values)
+        (dolist (value (or (cdr (assoc property css-value-class-alist))
+                           (cdr (assoc property css-property-alist))))
+          (if (stringp value)
+              (push value values)
+            (let ((new-values (css--property-values (symbol-name value))))
+              (setq values (append values new-values))))
+          (puthash property values css--property-value-cache))
+        values)))
+
+(defun css--complete-property-value ()
+  "Complete property value at point."
+  (let ((property
+         (save-excursion
+           (re-search-backward ":[^/]" (line-beginning-position) t)
+           (let ((property-end (point)))
+             (skip-chars-backward "-[:alnum:]")
+             (let ((property (buffer-substring (point) property-end)))
+               (car (assoc property css-property-alist)))))))
+    (when property
+      (let ((end (point)))
+        (save-excursion
+          (skip-chars-backward "[:graph:]")
+          (list (point) end
+                (cons "inherit" (css--property-values property))))))))
+
 (defun css-completion-at-point ()
   "Complete current symbol at point.
-Currently supports completion of CSS properties, pseudo-elements,
-pseudo-classes, and at-rules."
+Currently supports completion of CSS properties, property values,
+pseudo-elements, pseudo-classes, and at-rules."
   (or (css--complete-property)
+      (css--complete-property-value)
       (css--complete-pseudo-element-or-class)
       (css--complete-at-rule)))
 
-- 
2.7.0