If you don't want to install a plugin for this, you can also just write a couple of visual mode mappings:
This almost works:
xnoremap L dp`[v`]
xnoremap H dhP`[v`]
...but if you have virtualedit set to its default value, then at the end of the line H will move the selection too far to the left (because after the delete the cursor is before instead of after where the deleted text used to be).
We can fix this by using a slightly different mapping if we're at the end of the line via an expression mapping:
xnoremap <expr> H getpos("'>")[2] == len(getline('.')) ? 'dP`[v`]' : 'dhP`[v`]'
This works great unless we accidentally try to use H when we're at the start of the line, in which case it deletes the selected text!
We could fix it in a manner similar to the above, but an alternative is to make the mapping abort before performing the deletion if at the start of the line by prepending the following to the mappings:
"_y`>v`<hl
" First we ensure we're at the start of the selection:
"_y " Do a yank, discarding the yanked text
`> " Move to the end of the previous selection
v " Re-enter visual mode
`< " Move to the start of the previous selection
h " Move left. If at the start of the line, the mapping will stop here!
l " Move right again. Now we are ready to continue with our mapping.
The final mappings
Putting it all together, we end up with:
xnoremap L dp`[v`]
xnoremap <expr> H getpos("'>")[2] == len(getline('.'))
\ ? '"_y`>v`<hldP`[v`]'
\ : '"_y`>v`<hldhP`[v`]'