This is by design: programs that produce colored output typically do so only when their output goes to a terminal, not when it's sent to a pipe or to a regular file. The reason is that data sent on a terminal is presumably read by a human, whereas data piped to a program or written to a file is likely to be parsed by some program, so it shouldn't contain extraneous content like color-changing escape sequences.
ls displays colored output on a terminal when you pass the option
--color=auto). To force colored output regardless of the file type of the standard output, pass
--color=yes (they're synonyms). This convention has been followed by other commands, like GNU grep, FreeBSD grep,
git diff, etc.
ls --colors=yes -l | less
With the FreeBSD version of
ls (also found on OSX, and available as the
colorls port on OpenBSD and NetBSD), pass the option
-G to display colors when the output is a terminal. Set the environment
CLICOLOR_FORCE to display colors regardless of the output file type.
CLICOLOR_FORCE=1 ls -l | less