Assuming that your href attribute is always quoted, you can use this pattern:
$pattern = '~(?>\bhref\s*=\s*["\']|\G(?<!^))[^ "\']*+\K ~';
$result = preg_replace($pattern, '%20', $html);
pattern details:
~
(?> # open an atomic group (*)
\bhref\s*=\s*["\'] # attribute name until the quote
| # OR
\G(?<!^) # contiguous to a precedent match
) # close the atomic group
[^ "\']*+ # content that is not a space or quotes (optional)
\K # resets the start of the match from match result
[ ] # a space
~
(*) An atomic group is a non-capturing group where the regex engine is not allowed to backtrack.