@@ -655,7 +655,7 @@ blockToHtml opts (LineBlock lns) =
655655 return $ H.div ! A.class_ "line-block" $ htmlLines
656656blockToHtml opts (Div attr@(ident, classes, kvs') bs) = do
657657 html5 <- gets stHtml5
658− let kvs = kvs' ++
658+ let kvs = [(k,v) | (k,v) <- kvs', k /= "width"] ++
659659 if "column" `elem` classes
660660 then let w = fromMaybe "48%" (lookup "width" kvs')
661661 in [("style", "width:" ++ w ++ ";min-width:" ++ w ++
@@ -664,7 +664,12 @@ blockToHtml opts (Div attr@(ident, classes, kvs') bs) = do
664664 let speakerNotes = "notes" `elem` classes
665665 -- we don't want incremental output inside speaker notes, see #1394
666666 let opts' = if speakerNotes then opts{ writerIncremental = False } else opts
667− contents <- blockListToHtml opts' bs
667+ contents <- if "columns" `elem` classes
668+ then -- we don't use blockListToHtml because it inserts
669+ -- a newline between the column divs, which throws
670+ -- off widths! see #4028
671+ mconcat <$> mapM (blockToHtml opts) bs
672+ else blockListToHtml opts' bs
668673 let contents' = nl opts >> contents >> nl opts
669674 let (divtag, classes') = if html5 && "section" `elem` classes
670675 then (H5.section, filter (/= "section") classes)