diff --git a/Chart.cabal b/Chart.cabal
--- a/Chart.cabal
+++ b/Chart.cabal
@@ -1,5 +1,5 @@
 Name: Chart
-Version: 1.8.2
+Version: 1.8.3
 License: BSD3
 License-file: LICENSE
 Copyright: Tim Docker, 2006-2014
@@ -11,7 +11,7 @@
              Cairo (<http://hackage.haskell.org/package/Chart-cairo>)
              and
              Diagrams (<http://hackage.haskell.org/package/Chart-diagrams>).
-             
+
              Documentation: https://github.com/timbod7/haskell-chart/wiki.
 Category: Graphics
 Cabal-Version: >= 1.6
@@ -21,7 +21,7 @@
   Build-depends: base >= 3 && < 5
                , old-locale
                , time, mtl, array
-               , lens >= 3.9 && < 4.16
+               , lens >= 3.9 && < 4.17
                , colour >= 2.2.1 && < 2.4
                , data-default-class < 0.2
                , mtl >= 2.0 && < 2.3
@@ -41,6 +41,7 @@
         Graphics.Rendering.Chart.Axis.Floating,
         Graphics.Rendering.Chart.Axis.Indexed,
         Graphics.Rendering.Chart.Axis.Int,
+        Graphics.Rendering.Chart.Axis.Time,
         Graphics.Rendering.Chart.Axis.LocalTime,
         Graphics.Rendering.Chart.Axis.Types,
         Graphics.Rendering.Chart.Axis.Unit,
diff --git a/Graphics/Rendering/Chart/Axis.hs b/Graphics/Rendering/Chart/Axis.hs
--- a/Graphics/Rendering/Chart/Axis.hs
+++ b/Graphics/Rendering/Chart/Axis.hs
@@ -11,7 +11,7 @@
     module Graphics.Rendering.Chart.Axis.Types,
     module Graphics.Rendering.Chart.Axis.Floating,
     module Graphics.Rendering.Chart.Axis.Int,
-    module Graphics.Rendering.Chart.Axis.LocalTime,
+    module Graphics.Rendering.Chart.Axis.Time,
     module Graphics.Rendering.Chart.Axis.Unit,
     module Graphics.Rendering.Chart.Axis.Indexed,
 ) where
@@ -19,6 +19,6 @@
 import Graphics.Rendering.Chart.Axis.Types
 import Graphics.Rendering.Chart.Axis.Floating
 import Graphics.Rendering.Chart.Axis.Int
-import Graphics.Rendering.Chart.Axis.LocalTime
+import Graphics.Rendering.Chart.Axis.Time
 import Graphics.Rendering.Chart.Axis.Unit
 import Graphics.Rendering.Chart.Axis.Indexed
diff --git a/Graphics/Rendering/Chart/Axis/Floating.hs b/Graphics/Rendering/Chart/Axis/Floating.hs
--- a/Graphics/Rendering/Chart/Axis/Floating.hs
+++ b/Graphics/Rendering/Chart/Axis/Floating.hs
@@ -11,6 +11,7 @@
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
 
 module Graphics.Rendering.Chart.Axis.Floating(
     Percent(..),
diff --git a/Graphics/Rendering/Chart/Axis/Int.hs b/Graphics/Rendering/Chart/Axis/Int.hs
--- a/Graphics/Rendering/Chart/Axis/Int.hs
+++ b/Graphics/Rendering/Chart/Axis/Int.hs
@@ -5,6 +5,7 @@
 -- License     :  BSD-style (see chart/COPYRIGHT)
 --
 -- Calculate and render integer indexed axes
+{-# OPTIONS_GHC -fno-warn-orphans #-}
 
 module Graphics.Rendering.Chart.Axis.Int(
     defaultIntAxis,
diff --git a/Graphics/Rendering/Chart/Axis/LocalTime.hs b/Graphics/Rendering/Chart/Axis/LocalTime.hs
--- a/Graphics/Rendering/Chart/Axis/LocalTime.hs
+++ b/Graphics/Rendering/Chart/Axis/LocalTime.hs
@@ -8,21 +8,24 @@
 --
 -- Calculate and render time axes
 
-module Graphics.Rendering.Chart.Axis.LocalTime(
+module Graphics.Rendering.Chart.Axis.LocalTime
+    {-# DEPRECATED "Use Graphics.Rendering.Chart.Axis.Time module" #-}
+    (
     TimeSeq,
     TimeLabelFn,
     TimeLabelAlignment(..),
-    
+
     timeAxis,
     autoTimeAxis,
-    
+
     days, months, years,
-                  
+
     -- * Utilities
     doubleFromLocalTime
-    
-    ) where
- 
+
+    )
+    where
+
 import Data.Default.Class
 #if MIN_VERSION_time(1,5,0)
 import Data.Time hiding (months)
@@ -34,11 +37,7 @@
 import Control.Lens
 
 import Graphics.Rendering.Chart.Axis.Types
-
-instance PlotValue LocalTime where
-    toValue    = doubleFromLocalTime
-    fromValue  = localTimeFromDouble
-    autoAxis   = autoTimeAxis
+import Graphics.Rendering.Chart.Axis.Time ()
 
 ----------------------------------------------------------------------
 
@@ -89,19 +88,19 @@
 --
 --   The values to be plotted against this axis can be created with
 --   'doubleFromLocalTime'.
-timeAxis :: 
-  TimeSeq 
+timeAxis ::
+  TimeSeq
   -- ^ Set the minor ticks, and the final range will be aligned to its
   --   elements.
-  -> TimeSeq 
+  -> TimeSeq
   -- ^ Set the labels and grid.
-  -> TimeLabelFn 
-  -> TimeLabelAlignment 
-  -> TimeSeq 
+  -> TimeLabelFn
+  -> TimeLabelAlignment
+  -> TimeSeq
   -- ^ Set the second line of labels.
-  -> TimeLabelFn 
+  -> TimeLabelFn
   -- ^ Format `LocalTime` for labels.
-  -> TimeLabelAlignment 
+  -> TimeLabelAlignment
   -> AxisFn LocalTime
 timeAxis tseq lseq labelf lal cseq contextf clal pts = AxisData {
     _axis_visibility = def,
@@ -110,7 +109,7 @@
     _axis_ticks    = [ (t,2) | t <- times] ++ [ (t,5) | t <- ltimes, visible t],
     _axis_labels   = [ [ (t,l) | (t,l) <- labels labelf   ltimes lal, visible t]
                      , [ (t,l) | (t,l) <- labels contextf ctimes clal, visible t]
-                     ], 
+                     ],
     _axis_grid     = [ t     | t <- ltimes, visible t]
     }
   where
@@ -235,9 +234,9 @@
 autoTimeAxis pts
     | null pts              = timeAxis days    days    (ft "%d-%b-%y") UnderTicks
                                                noTime  (ft "") UnderTicks []
-    | tdiff==0 && 100*dsec<1= timeAxis millis1   millis1  (ft "%S%Q") UnderTicks 
+    | tdiff==0 && 100*dsec<1= timeAxis millis1   millis1  (ft "%S%Q") UnderTicks
                                                  noTime (ft "%S%Q") UnderTicks pts
-    | tdiff==0 && 10*dsec<1 = timeAxis millis10  millis10  (ft "%S%Q") UnderTicks 
+    | tdiff==0 && 10*dsec<1 = timeAxis millis10  millis10  (ft "%S%Q") UnderTicks
                                                  noTime (ft "%S%Q") UnderTicks pts
     | tdiff==0 && dsec<1    = timeAxis millis10  millis100 (ft "%S%Q") UnderTicks
                                                  seconds (ft "%M:%S") BetweenTicks pts
diff --git a/Graphics/Rendering/Chart/Axis/Time.hs b/Graphics/Rendering/Chart/Axis/Time.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/Rendering/Chart/Axis/Time.hs
@@ -0,0 +1,316 @@
+{-# LANGUAGE CPP #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Graphics.Rendering.Chart.Axis.Time
+-- Copyright   :  (c) Tim Docker 2010, 2014
+-- License     :  BSD-style (see chart/COPYRIGHT)
+--
+-- Calculate and render time axes
+
+module Graphics.Rendering.Chart.Axis.Time(
+    TimeSeq,
+    TimeLabelFn,
+    TimeLabelAlignment(..),
+
+    TimeValue (..),
+
+    timeValueAxis,
+    autoTimeValueAxis,
+
+    days, months, years,
+
+    ) where
+
+import Data.Default.Class
+#if MIN_VERSION_time(1,5,0)
+import Data.Time hiding (months)
+#else
+import Data.Time
+import System.Locale (defaultTimeLocale)
+#endif
+import Data.Fixed
+import Control.Lens
+
+import Graphics.Rendering.Chart.Axis.Types
+import Graphics.Rendering.Chart.Geometry (Range)
+
+-- | A typeclass abstracting the functions we need
+-- to be able to plot against an axis of time type @d@.
+class TimeValue t where
+    utctimeFromTV :: t -> UTCTime
+    tvFromUTCTime :: UTCTime -> t
+
+    {-# MINIMAL utctimeFromTV, tvFromUTCTime #-}
+
+    doubleFromTimeValue  :: t -> Double
+    doubleFromTimeValue = doubleFromTimeValue . utctimeFromTV
+
+    timeValueFromDouble  :: Double -> t
+    timeValueFromDouble = tvFromUTCTime . timeValueFromDouble
+
+instance TimeValue UTCTime where
+    utctimeFromTV       = id
+    tvFromUTCTime       = id
+    doubleFromTimeValue = doubleFromUTCTime
+    timeValueFromDouble = utcTimeFromDouble
+
+instance TimeValue Day where
+    utctimeFromTV d     = UTCTime d 0
+    tvFromUTCTime       = utctDay
+    doubleFromTimeValue = doubleFromDay
+    timeValueFromDouble = dayFromDouble
+
+instance TimeValue LocalTime where
+    utctimeFromTV (LocalTime d tod) = UTCTime d (timeOfDayToTime tod)
+    tvFromUTCTime (UTCTime d dt)    = LocalTime d (timeToTimeOfDay dt)
+
+----------------------------------------------------------------------
+
+instance PlotValue LocalTime where
+    toValue    = doubleFromTimeValue
+    fromValue  = timeValueFromDouble
+    autoAxis   = autoTimeValueAxis
+
+instance PlotValue UTCTime where
+    toValue    = doubleFromTimeValue
+    fromValue  = timeValueFromDouble
+    autoAxis   = autoTimeValueAxis
+
+instance PlotValue Day where
+    toValue    = doubleFromTimeValue
+    fromValue  = timeValueFromDouble
+    autoAxis   = autoTimeValueAxis
+
+----------------------------------------------------------------------
+
+-- | Map a UTCTime value to a plot coordinate.
+doubleFromUTCTime :: UTCTime -> Double
+doubleFromUTCTime ut = fromIntegral (toModifiedJulianDay (utctDay ut))
+              + fromRational (timeOfDayToDayFraction (timeToTimeOfDay (utctDayTime ut)))
+
+-- | Map a plot coordinate to a UTCTime.
+utcTimeFromDouble :: Double -> UTCTime
+utcTimeFromDouble v =
+  UTCTime (ModifiedJulianDay i) (timeOfDayToTime (dayFractionToTimeOfDay (toRational d)))
+ where
+   (i,d) = properFraction v
+
+-- | Map a Day value to a plot coordinate.
+doubleFromDay :: Day -> Double
+doubleFromDay d = fromIntegral (toModifiedJulianDay d)
+
+-- | Map a plot coordinate to a Day.
+dayFromDouble :: Double -> Day
+dayFromDouble v = ModifiedJulianDay (truncate v)
+
+----------------------------------------------------------------------
+
+-- | TimeSeq is a (potentially infinite) set of times. When passed
+--   a reference time, the function returns a a pair of lists. The first
+--   contains all times in the set less than the reference time in
+--   decreasing order. The second contains all times in the set greater
+--   than or equal to the reference time, in increasing order.
+type TimeSeq = UTCTime -> ([UTCTime],[UTCTime])
+
+coverTS :: TimeSeq -> UTCTime -> UTCTime -> [UTCTime]
+coverTS tseq minT maxT = min' ++ enumerateTS tseq minT maxT ++ max'
+  where
+    min' =  if elemTS minT tseq then [] else take 1 (fst (tseq minT))
+    max' =  if elemTS maxT tseq then [] else take 1 (snd (tseq maxT))
+
+enumerateTS :: TimeSeq -> UTCTime -> UTCTime -> [UTCTime]
+enumerateTS tseq minT maxT =
+    reverse (takeWhile (>=minT) ts1)  ++ takeWhile (<=maxT) ts2
+  where
+    (ts1,ts2) = tseq minT
+
+elemTS :: UTCTime -> TimeSeq -> Bool
+elemTS t tseq = case tseq t of
+    (_,t0:_) | t == t0 -> True
+    _                  -> False
+
+-- | How to display a time
+type TimeLabelFn = UTCTime -> String
+
+data TimeLabelAlignment = UnderTicks
+                        | BetweenTicks
+                        deriving (Show)
+
+-- | Create an 'AxisFn' to for a time axis.
+--
+--   The values to be plotted against this axis can be created with
+--   'doubleFromLocalTime'.
+--
+--   Implementation detail: 'PlotValue' constraint is needed to use `vmap`.
+timeValueAxis ::
+  TimeValue t
+  => TimeSeq
+  -- ^ Set the minor ticks, and the final range will be aligned to its
+  --   elements.
+  -> TimeSeq
+  -- ^ Set the labels and grid.
+  -> TimeLabelFn
+  -> TimeLabelAlignment
+  -> TimeSeq
+  -- ^ Set the second line of labels.
+  -> TimeLabelFn
+  -- ^ Format @t@ for labels.
+  -> TimeLabelAlignment
+  -> AxisFn t
+timeValueAxis tseq lseq labelf lal cseq contextf clal pts = AxisData {
+    _axis_visibility = def,
+    _axis_viewport = vmap' (min', max'),
+    _axis_tropweiv = invmap' (min', max'),
+    _axis_ticks    = [ (tvFromUTCTime t,2) | t <- times] ++ [ (tvFromUTCTime t,5) | t <- ltimes, visible t],
+    _axis_labels   = [ [ (tvFromUTCTime t,l) | (t,l) <- labels labelf   ltimes lal, visible t]
+                     , [ (tvFromUTCTime t,l) | (t,l) <- labels contextf ctimes clal, visible t]
+                     ],
+    _axis_grid     = [ tvFromUTCTime t     | t <- ltimes, visible t]
+    }
+  where
+    (minT,maxT)  = case pts of
+                       [] -> (refTimeValue,refTimeValue)
+                       ps -> (minimum (map utctimeFromTV ps), maximum (map utctimeFromTV ps))
+    refTimeValue = timeValueFromDouble 0
+
+    times, ltimes, ctimes :: [UTCTime]
+    times        = coverTS tseq minT maxT
+    ltimes       = coverTS lseq minT maxT
+    ctimes       = coverTS cseq minT maxT
+    min'         = minimum times
+    max'         = maximum times
+    visible t    = min' <= t && t <= max'
+    labels f ts lal' =
+        [ (align lal' m1' m2', f m1)
+          | (m1,m2) <- zip ts (tail ts)
+          , let m1' = if m1<min' then min' else m1
+          , let m2' = if m2>max' then max' else m2 ]
+
+    align BetweenTicks m1 m2 = avg m1 m2
+    align UnderTicks   m1 _  = m1
+
+    avg m1 m2    = timeValueFromDouble $ m1' + (m2' - m1')/2
+     where
+      m1' = doubleFromTimeValue m1
+      m2' = doubleFromTimeValue m2
+
+vmap' :: TimeValue x => (UTCTime,UTCTime) -> Range -> x -> Double
+vmap' (v1,v2) (v3,v4) v = v3 + (doubleFromTimeValue v - doubleFromTimeValue v1) * (v4-v3)
+                              / (doubleFromTimeValue v2 - doubleFromTimeValue v1)
+
+invmap' :: TimeValue x => (UTCTime,UTCTime) -> Range -> Double -> x
+invmap' (v3,v4) (d1,d2) d = timeValueFromDouble (doubleFromTimeValue v3 + ( (d-d1) * doubleRange
+                                                   / (d2-d1) ))
+    where doubleRange = doubleFromTimeValue v4 - doubleFromTimeValue v3
+
+truncateTo :: Real a => a -> a -> a
+truncateTo t step = t - t `mod'` step
+
+secondSeq :: NominalDiffTime -> TimeSeq
+secondSeq step t@(UTCTime day dt) = (iterate rev t1, tail (iterate fwd t1))
+  where t0       = UTCTime day (truncateTo dt step')
+        t1       = if t0 < t then t0 else rev t0
+        rev      = addUTCTime (negate step)
+        fwd      = addUTCTime step
+        step'    = realToFrac step
+
+millis1, millis10, millis100, seconds, fiveSeconds :: TimeSeq
+millis1 = secondSeq (1 / 1000)
+millis10 = secondSeq (1 / 100)
+millis100 = secondSeq (1 / 10)
+seconds = secondSeq 1
+fiveSeconds = secondSeq 5
+
+minutes, fiveMinutes :: TimeSeq
+minutes = secondSeq 60
+fiveMinutes = secondSeq (5 * 60)
+
+-- | A 'TimeSeq' for hours.
+hours :: TimeSeq
+hours = secondSeq (60 * 60)
+
+-- | A 'TimeSeq' for calendar days.
+days :: TimeSeq
+days t = (map toTime $ iterate rev t1, map toTime $ tail (iterate fwd t1))
+  where t0       = utctDay t
+        t1       = if toTime t0 < t then t0 else rev t0
+        rev      = pred
+        fwd      = succ
+        toTime d = UTCTime d 0
+
+-- | A 'TimeSeq' for calendar months.
+months :: TimeSeq
+months t = (map toTime $ iterate rev t1, map toTime $ tail (iterate fwd t1))
+  where t0       = let (y,m,_) = toGregorian $ utctDay t in fromGregorian y m 1
+        t1       = if toTime t0 < t then t0 else rev t0
+        rev      = addGregorianMonthsClip (-1)
+        fwd      = addGregorianMonthsClip 1
+        toTime d = UTCTime d 0
+
+-- | A 'TimeSeq' for calendar years.
+years :: TimeSeq
+years t = (map toTime $ iterate rev t1, map toTime $ tail (iterate fwd t1))
+  where t0       = toGregorian (utctDay t) ^. _1
+        t1       = if toTime t0 < t then t0 else rev t0
+        rev      = pred
+        fwd      = succ
+        toTime y = UTCTime (fromGregorian y 1 1) 0
+
+-- | A 'TimeSeq' for no sequence at all.
+noTime :: TimeSeq
+noTime _ = ([],[])
+
+-- | Automatically choose a suitable time axis, based upon the time range
+--   of data.  The values to be plotted against this axis can be created
+--   with 'doubleFromTimeValue'.
+autoTimeValueAxis :: TimeValue t => AxisFn t
+autoTimeValueAxis pts
+    | null pts     = timeValueAxis days    days    (ft "%d-%b-%y") UnderTicks
+                                           noTime  (ft "") UnderTicks []
+    | 100*dsec<1   = timeValueAxis millis1   millis1  (ft "%S%Q") UnderTicks
+                                             noTime (ft "%S%Q") UnderTicks pts
+    | 10*dsec<1    = timeValueAxis millis10  millis10  (ft "%S%Q") UnderTicks
+                                             noTime (ft "%S%Q") UnderTicks pts
+    | dsec<1       = timeValueAxis millis10  millis100 (ft "%S%Q") UnderTicks
+                                             seconds (ft "%M:%S") BetweenTicks pts
+    | dsec<5       = timeValueAxis millis100 seconds (ft "%M:%S%Q") UnderTicks
+                                             seconds (ft "%M:%S") BetweenTicks pts
+    | dsec<32      = timeValueAxis seconds seconds (ft "%Ss") UnderTicks
+                                           minutes (ft "%d-%b-%y %H:%M") BetweenTicks pts
+    | dsec<120     = timeValueAxis seconds fiveSeconds (ft "%Ss") UnderTicks
+                                           minutes (ft "%d-%b-%y %H:%M") BetweenTicks pts
+    | dsec<7*60    = timeValueAxis fiveSeconds minutes (ft "%Mm") UnderTicks
+                                           hours   (ft "%d-%b-%y %H:00") BetweenTicks pts
+    | dsec<32*60   = timeValueAxis minutes minutes (ft "%Mm") UnderTicks
+                                           hours   (ft "%d-%b-%y %H:00") BetweenTicks pts
+    | dsec<90*60   = timeValueAxis minutes fiveMinutes (ft "%Mm") UnderTicks
+                                           hours   (ft "%d-%b-%y %H:00") BetweenTicks pts
+    | dsec<4*3600  = timeValueAxis fiveMinutes hours (ft "%H:%M") UnderTicks
+                                               days  (ft "%d-%b-%y") BetweenTicks pts
+    | dsec<32*3600 = timeValueAxis hours  hours  (ft "%H:%M") UnderTicks
+                                          days   (ft "%d-%b-%y") BetweenTicks pts
+    | dday<4       = timeValueAxis hours  days   (ft "%d-%b-%y") BetweenTicks
+                                          noTime (ft "") BetweenTicks pts
+    | dday<12      = timeValueAxis days   days   (ft "%d-%b") BetweenTicks
+                                          years  (ft "%Y") BetweenTicks pts
+    | dday<45      = timeValueAxis days   days   (ft "%d") BetweenTicks
+                                          months (ft "%b-%y") BetweenTicks pts
+    | dday<95      = timeValueAxis days   months (ft "%b-%y") BetweenTicks
+                                          noTime (ft "") BetweenTicks pts
+    | dday<450     = timeValueAxis months months (ft "%b-%y") BetweenTicks
+                                          noTime (ft "") BetweenTicks pts
+    | dday<735     = timeValueAxis months months (ft "%b") BetweenTicks
+                                          years  (ft "%Y") BetweenTicks pts
+    | dday<1800    = timeValueAxis months years (ft "%Y") BetweenTicks
+                                          noTime (ft "") BetweenTicks pts
+    | otherwise    = timeValueAxis years  years (ft "%Y") BetweenTicks
+                                          noTime (ft "") BetweenTicks pts
+  where
+    upts  = map utctimeFromTV pts
+    dsec  = diffUTCTime t1 t0  -- seconds
+    dday  = dsec / 86400       -- days
+    t1    = maximum upts
+    t0    = minimum upts
+    ft    = formatTime defaultTimeLocale
diff --git a/Graphics/Rendering/Chart/Axis/Unit.hs b/Graphics/Rendering/Chart/Axis/Unit.hs
--- a/Graphics/Rendering/Chart/Axis/Unit.hs
+++ b/Graphics/Rendering/Chart/Axis/Unit.hs
@@ -5,6 +5,7 @@
 -- License     :  BSD-style (see chart/COPYRIGHT)
 --
 -- Calculate and render unit indexed axes
+{-# OPTIONS_GHC -fno-warn-orphans #-}
 
 module Graphics.Rendering.Chart.Axis.Unit(
     unitAxis,
diff --git a/Graphics/Rendering/Chart/Layout.hs b/Graphics/Rendering/Chart/Layout.hs
--- a/Graphics/Rendering/Chart/Layout.hs
+++ b/Graphics/Rendering/Chart/Layout.hs
@@ -18,6 +18,7 @@
 -- 
 --     * 'LayoutAxis'
 --
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE ExistentialQuantification #-}
@@ -96,6 +97,10 @@
   , slayouts_compress_legend
   ) where
 
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative ((<$>))
+#endif
+
 import Graphics.Rendering.Chart.Axis
 import Graphics.Rendering.Chart.Geometry
 import Graphics.Rendering.Chart.Drawing
@@ -109,6 +114,7 @@
 import Data.Colour
 import Data.Colour.Names (white)
 import Data.Default.Class
+import Data.Maybe (fromMaybe)
 
 -- | A @MAxisFn@ is a function that generates an (optional) axis
 --   given the points plotted against that axis.
@@ -212,13 +218,19 @@
 layoutToGrid :: forall x y . (Ord x, Ord y) => Layout x y -> Grid (Renderable (LayoutPick x y y))
 layoutToGrid l = grid
   where
-    grid = titleToRenderable lm (_layout_title_style l) (_layout_title l)
-           `wideAbove`
-           addMarginsToGrid (lm,lm,lm,lm) (layoutPlotAreaToGrid l)
-           `aboveWide` 
-           renderLegend l (getLegendItems l)
+    lp :: Grid a -> a -> Grid a
+    lp = case fromMaybe LegendBelow $ _legend_position <$> _layout_legend l of
+              LegendAbove -> flip wideAbove
+              LegendBelow -> aboveWide
+              LegendRight -> besideTall
+              LegendLeft  -> flip tallBeside
+
+    title = titleToRenderable lm (_layout_title_style l) (_layout_title l)
+    plotArea = addMarginsToGrid (lm,lm,lm,lm) (layoutPlotAreaToGrid l)
+    legend = renderLegend l (getLegendItems l)
+    grid = title `wideAbove` (plotArea `lp` legend)
     lm = _layout_margin l
-  
+
 getLayoutXVals :: Layout x y -> [x]
 getLayoutXVals l = concatMap (fst . _plot_all_points) (_layout_plots l)
 
diff --git a/Graphics/Rendering/Chart/Legend.hs b/Graphics/Rendering/Chart/Legend.hs
--- a/Graphics/Rendering/Chart/Legend.hs
+++ b/Graphics/Rendering/Chart/Legend.hs
@@ -12,11 +12,13 @@
     Legend(..),
     LegendStyle(..),
     LegendOrientation(..),
+    LegendPosition(..),
     legendToRenderable,
     legend_label_style,
     legend_margin,
     legend_plot_size,
-    legend_orientation
+    legend_orientation,
+    legend_position
 ) where
 
 import Data.List (partition,intersperse)
@@ -35,7 +37,8 @@
    _legend_label_style :: FontStyle,
    _legend_margin      :: Double,
    _legend_plot_size   :: Double,
-   _legend_orientation :: LegendOrientation
+   _legend_orientation :: LegendOrientation,
+   _legend_position    :: LegendPosition
 }
 
 -- | Legends can be constructed in two orientations: in rows
@@ -43,8 +46,13 @@
 -- columns (where we specify the maximum number of rows)
 data LegendOrientation = LORows Int
                        | LOCols Int
-                       
 
+-- | Defines the position of the legend, relative to the plot.
+data LegendPosition = LegendAbove
+                    | LegendBelow
+                    | LegendRight
+                    | LegendLeft
+
 data Legend x y = Legend LegendStyle [(String, Rect -> BackendProgram ())]
 
 instance ToRenderable (Legend x y) where
@@ -83,7 +91,7 @@
         rp :: (Rect -> BackendProgram ()) -> Grid (Renderable String)
         rp rfn = tval Renderable {
                      minsize = return (_legend_plot_size ls, 0),
-                     render  = \(w,h) -> do 
+                     render  = \(w,h) -> do
                          _ <- rfn (Rect (Point 0 0) (Point w h))
                          return (\_-> Just title)
                  }
@@ -93,7 +101,7 @@
     ggap2 = tval $ spacer1 (lbl "X")
 
     lbl :: String -> Renderable String
-    lbl = label (_legend_label_style ls) HTA_Left VTA_Centre 
+    lbl = label (_legend_label_style ls) HTA_Left VTA_Centre
 
 groups :: Int -> [a] -> [[a]]
 groups _ [] = []
@@ -105,11 +113,12 @@
 join_nub []          = []
 
 instance Default LegendStyle where
-  def = LegendStyle 
+  def = LegendStyle
     { _legend_label_style = def
     , _legend_margin      = 20
     , _legend_plot_size   = 20
     , _legend_orientation = LORows 4
+    , _legend_position    = LegendBelow
     }
 
 $( makeLenses ''LegendStyle )
diff --git a/Graphics/Rendering/Chart/Plot/Vectors.hs b/Graphics/Rendering/Chart/Plot/Vectors.hs
--- a/Graphics/Rendering/Chart/Plot/Vectors.hs
+++ b/Graphics/Rendering/Chart/Plot/Vectors.hs
@@ -6,6 +6,7 @@
 --
 -- Vector plots
 --
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TemplateHaskell #-}
 
 module Graphics.Rendering.Chart.Plot.Vectors(
@@ -24,7 +25,9 @@
 
 import Control.Lens
 import Control.Monad
+#if !MIN_VERSION_base(4,8,0)
 import Control.Applicative
+#endif
 import Data.Tuple
 import Data.Colour hiding (over)
 import Data.Colour.Names
diff --git a/Graphics/Rendering/Chart/Renderable.hs b/Graphics/Rendering/Chart/Renderable.hs
--- a/Graphics/Rendering/Chart/Renderable.hs
+++ b/Graphics/Rendering/Chart/Renderable.hs
@@ -8,6 +8,7 @@
 -- is a composable drawing element, along with assorted functions to
 -- them.
 --
+{-# LANGUAGE DeriveFunctor #-}
 {-# LANGUAGE TemplateHaskell #-}
 
 module Graphics.Rendering.Chart.Renderable(
@@ -69,10 +70,14 @@
    --   The resulting "pick" function  maps a point in the image to a value.
    render  :: RectSize -> BackendProgram (PickFn a)
 }
+  deriving (Functor)
 
 -- | A type class abtracting the conversion of a value to a Renderable.
 class ToRenderable a where
   toRenderable :: a -> Renderable ()
+
+instance ToRenderable (Renderable a) where
+  toRenderable = void
 
 emptyRenderable :: Renderable a
 emptyRenderable = spacer (0,0)
