diff --git a/ginger.cabal b/ginger.cabal
--- a/ginger.cabal
+++ b/ginger.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                ginger
-version:             0.2.7.0
+version:             0.2.8.0
 synopsis:            An implementation of the Jinja2 template language in Haskell
 description:         Ginger is Jinja, minus the most blatant pythonisms. Wants
                      to be feature complete, but isn't quite there yet.
diff --git a/src/Text/Ginger/Parse.hs b/src/Text/Ginger/Parse.hs
--- a/src/Text/Ginger/Parse.hs
+++ b/src/Text/Ginger/Parse.hs
@@ -48,6 +48,7 @@
 import Data.List ( foldr, nub, sort )
 import Data.HashMap.Strict (HashMap)
 import qualified Data.HashMap.Strict as HashMap
+import Data.Default ( Default (..) )
 
 import System.FilePath ( takeDirectory, (</>) )
 
@@ -575,8 +576,23 @@
 
 arrayAccessP :: Monad m => Parser m (Expression -> Expression)
 arrayAccessP = do
-    i <- bracedP "[" "]" expressionP
-    return $ \e -> MemberLookupE e i
+    bracedP "[" "]" inner
+    where
+        inner = try sliceInner <|> indexInner
+        sliceInner = do
+            offset <- option NullLiteralE (try expressionP)
+            char ':'
+            length <- option NullLiteralE (try expressionP)
+            return $ \e ->
+                CallE
+                    (VarE "slice")
+                    [ (Nothing, e)
+                    , (Nothing, offset)
+                    , (Nothing, length)
+                    ]
+        indexInner = do
+            i <- expressionP
+            return $ \e -> MemberLookupE e i
 
 funcCallP :: Monad m => Parser m (Expression -> Expression)
 funcCallP = do
diff --git a/src/Text/Ginger/Run/Builtins.hs b/src/Text/Ginger/Run/Builtins.hs
--- a/src/Text/Ginger/Run/Builtins.hs
+++ b/src/Text/Ginger/Run/Builtins.hs
@@ -206,18 +206,24 @@
                 lengthInt = fmap Prelude.round . asNumber $ length
 
                 slice :: [a] -> Int -> Maybe Int -> [a]
-                slice xs start Nothing =
-                    Prelude.drop start xs
+                slice xs start Nothing
+                    | start < 0 =
+                        Prelude.drop (Prelude.length xs + start) xs
+                    | otherwise =
+                        Prelude.drop start xs
                 slice xs start (Just length) =
-                    Prelude.take length . Prelude.drop start $ xs
+                    Prelude.take length $ slice xs start Nothing
             case asDictItems slicee of
                 Just items -> do
                     let slicedItems = slice items startInt lengthInt
                     return $ dict slicedItems
-                Nothing -> do
-                    let items = fromMaybe [] $ asList slicee
-                        slicedItems = slice items startInt lengthInt
-                    return $ toGVal slicedItems
+                Nothing ->
+                    case asList slicee of
+                    Just items ->
+                        return . toGVal $ slice items startInt lengthInt
+                    Nothing ->
+                        return . toGVal . Text.pack $
+                            slice (Text.unpack $ asText slicee) startInt lengthInt
         _ -> fail "Invalid arguments to 'slice'"
 
 gfnReplace :: Monad m => Function (Run m h)
