Można albo dużymi edytorami w stylu FCKeditor czy TinyMCE, albo czymś tak prostym jak ta moja mała funkcyjka w JS

field -> id_pola typu textarea
strBefore -> tag początkowy czyli przykładowo <b>
strAfter -> tag końcowy czyli przykładowo </b>
Ja go daję jako zdarzenie onclick dla jakiegoś guzika

Zaznaczony tekst może być jak widać także listą i wtedy każde linia złamana przez enter zostanie uznana jako element listy.
To taki banalny przykład na szybkie zastosowanie JS bez sięgania od razu do frameworków typu jQuery. Działa z tego co wiem na wszystkich przeglądarkach

function putTag(field, strBefore, strAfter) {
element = document.getElementById(field);
element.focus();
// IE
if (document.selection) {
var oRange = document.selection.createRange();
var numLen = oRange.text.length;
if(strBefore == "<ol><li>" || strBefore == "<ul><li>") {
oRange.text.replaceAll("\n", "</li><li>");
}
oRange.text = strBefore + oRange.text + strAfter;
return false;
// FF i Opera
} else if (element.setSelectionRange) {
var selStart = element.selectionStart, selEnd = element.selectionEnd;
var oldScrollTop = element.scrollTop;
if(strBefore == "<ol><li>" || strBefore == "<ul><li>") {
oRange = element.value.substring(selStart, selEnd).replaceAll("\n", "</li><li>");
} else {
oRange = element.value.substring(selStart, selEnd);
}
element.value = element.value.substring(0, selStart) + strBefore + oRange + strAfter + element.value.substring(selEnd);
element.setSelectionRange(selStart + strBefore.length, selEnd + strBefore.length);
element.scrollTop = oldScrollTop;
element.focus();
} else {
var oldScrollTop = element.scrollTop;
element.value += strBefore + strAfter;
element.scrollTop = oldScrollTop;
element.focus();
}
}