There must be a better / shorter way to do this:
# Find files that contain in current directory
# (including sub directories)
$ find .
find . -name \*.html
or, if you want to find files with names matching a regular expression:
find . -regex filename-regex.\*\.html
or, if you want to search for a regular expression in files with names matching a regular expression
find . -regex filename-regex.\*\.html -exec grep -H string-to-find {} \;
The grep argument -H outputs the name of the file, if that's of interest. If not, you can safely remove it and simply use grep. This will instruct find to execute grep string-to-find filename for each file name it finds, thus avoiding the possibility of the list of arguments being too long, and the need for find to finish executing before it can pass its results to xargs.
To address your examples:
find . | xargs grep
could be replaced with
find . -exec grep -H string-to-find {} \;
and
find . | grep html$ | xargs grep
could be replaced with
find . -name \*.html -exec grep -H string-to-find {} \;