diff --git a/mo/web/acct.py b/mo/web/acct.py
index a07888d3dd7b1682c5e3bbf0102374e26097384a..22865e22870e5cb5eacb7a48d1209f4e575a0d83 100644
--- a/mo/web/acct.py
+++ b/mo/web/acct.py
@@ -13,7 +13,6 @@ from typing import Optional, Dict
 import werkzeug.exceptions
 import wtforms
 from wtforms import validators, ValidationError
-from wtforms.fields.html5 import EmailField
 
 import mo.config as config
 import mo.db as db
@@ -28,7 +27,7 @@ import mo.web.fields as mo_fields
 class LoginForm(FlaskForm):
     next = wtforms.HiddenField()
     email = mo_fields.Email(validators=[validators.DataRequired()])
-    passwd = wtforms.PasswordField('Heslo')
+    passwd = mo_fields.Password('Heslo')
     submit = wtforms.SubmitField('Přihlásit se')
     reset = wtforms.SubmitField('Zapomenuté heslo')
 
@@ -127,7 +126,7 @@ def user_settings():
 
 class SettingsForm(FlaskForm):
     email = mo_fields.Email(validators=[validators.DataRequired()])
-    current_passwd = wtforms.PasswordField('Aktuální heslo', validators=[validators.DataRequired()])
+    current_passwd = mo_fields.Password('Aktuální heslo', validators=[validators.DataRequired()])
     new_passwd = mo_fields.NewPassword(
         description=mo.users.password_help + ' Pokud nechcete heslo měnit, ponechte toto políčko prázdné.',
     )
@@ -354,7 +353,7 @@ class Reg1:
 class Reg1Form(FlaskForm):
     email = mo_fields.Email(validators=[validators.DataRequired()])
     token = wtforms.HiddenField()
-    captcha = wtforms.StringField('Kontrolní odpověď', validators=[validators.DataRequired()])
+    captcha = mo_fields.String('Kontrolní odpověď', validators=[validators.DataRequired()])
     submit = wtforms.SubmitField('Vytvořit účet')
 
 
diff --git a/mo/web/fields.py b/mo/web/fields.py
index 85eeb71fb6655b2f6f2b047968c7d92ee0c949ad..5fcbb6b0c63b460973b63dae11bf2d8fa5224a11 100644
--- a/mo/web/fields.py
+++ b/mo/web/fields.py
@@ -9,6 +9,19 @@ import mo.users
 import mo.db as db
 
 
+class Stripped:
+    """Zkombinuje se s třídou z WTForms a přidá automatické ořezávání mezer."""
+
+    def process_formdata(self, valuelist):
+        if valuelist:
+            valuelist = [x.strip() for x in valuelist]
+        super().process_formdata(valuelist)
+
+
+class String(Stripped, wtforms.StringField):
+    pass
+
+
 class OptionalInt(wtforms.IntegerField):
     widget = NumberInput()
 
@@ -40,7 +53,7 @@ class Decimal(wtforms.DecimalField):
         return super(Decimal, self)._value()
 
 
-class IntList(wtforms.StringField):
+class IntList(String):
     list = None
 
     def __init__(self, label="", validators=None, **kwargs):
@@ -54,13 +67,13 @@ class IntList(wtforms.StringField):
             except mo.CheckError as e:
                 raise wtforms.ValidationError(str(e))
 
+
 class Points(Decimal):
     def __init__(self, label="Body", validators=None, **kwargs):
         super().__init__(label, validators, **kwargs)
 
 
-
-class Email(EmailField):
+class Email(Stripped, EmailField):
     def __init__(self, label="E-mail", validators=None, **kwargs):
         super().__init__(label, validators, **kwargs)
 
@@ -72,7 +85,7 @@ class Email(EmailField):
                 raise wtforms.ValidationError(str(e))
 
 
-class Grade(wtforms.StringField):
+class Grade(String):
     """Pro validaci hledá ve formuláři form.school a podle ní rozlišuje SŠ a ZŠ """
     default_description = "Pro základní školy je to číslo od 1 do 9, pro <var>k</var>-tý ročník <var>r</var>-leté střední školy má formát <var>k</var>/<var>r</var>."
     validate_grade = True
@@ -104,7 +117,7 @@ class BirthYear(OptionalInt):
                 raise wtforms.ValidationError(str(e))
 
 
-class Name(wtforms.StringField):
+class Name(String):
     def pre_validate(field, form):
         # XXX: Tato kontrola úmyslně není striktní, aby prošla i jména jako 'de Beer'
         if field.data:
@@ -124,7 +137,7 @@ class LastName(Name):
         super().__init__(label, validators, **kwargs)
 
 
-class Place(wtforms.StringField):
+class Place(String):
     def __init__(self, label="Místo", validators=None, **kwargs):
         super().__init__(label, validators, **kwargs)
         self.render_kw = {"placeholder": "Kód"}
@@ -142,7 +155,7 @@ class Place(wtforms.StringField):
                 field.place_error = "Zadané místo nenalezeno."
 
     def get_place(field) -> Optional[db.Place]:
-        """ Kešuje výsledek v field.place"""
+        """Kešuje výsledek v field.place"""
         if not field.place_loaded:
             field.place_loaded = True
             field.load_place()
@@ -182,7 +195,11 @@ class School(Place):
                 field.place_error = str(e)
 
 
-class NewPassword(wtforms.PasswordField):
+class Password(Stripped, wtforms.PasswordField):
+    pass
+
+
+class NewPassword(Password):
     def __init__(self, label="Nové heslo", validators=None, **kwargs):
         super().__init__(label, validators, **kwargs)
 
@@ -192,7 +209,7 @@ class NewPassword(wtforms.PasswordField):
                 raise wtforms.ValidationError(mo.users.password_help)
 
 
-class RepeatPassword(wtforms.PasswordField):
+class RepeatPassword(Password):
     """Pro validaci hledá ve formuláři form.new_passwd a s ním porovnává."""
 
     def __init__(self, label="Zopakujte heslo", validators=None, **kwargs):
diff --git a/mo/web/org_contest.py b/mo/web/org_contest.py
index 5459ba280cd6eab754599ae8c6087cce92a9d576..d9269c633c23fef9d13fa38fbb9324df2732d8ad 100644
--- a/mo/web/org_contest.py
+++ b/mo/web/org_contest.py
@@ -670,7 +670,7 @@ class SubmitForm(FlaskForm):
 
 
 class SetFinalForm(FlaskForm):
-    type = wtforms.StringField()
+    type = mo_fields.String()
     paper_id = wtforms.IntegerField()
     submit_final = wtforms.SubmitField("Prohlásit za finální")
 
diff --git a/mo/web/org_place.py b/mo/web/org_place.py
index 1d6b0c1e47db58b29db540656893524f024df4c6..7ffbc4a3a6d8a2d1dde7af974d80bf0f3def8e44 100644
--- a/mo/web/org_place.py
+++ b/mo/web/org_place.py
@@ -50,30 +50,30 @@ def org_place(id: int):
 
 
 class PlaceEditForm(FlaskForm):
-    name = wtforms.StringField(
+    name = mo_fields.String(
         'Název', render_kw={'autofocus': True},
         validators=[validators.DataRequired()]
     )
-    code = wtforms.StringField(
+    code = mo_fields.String(
         'Kód', filters=[lambda x: x or None],  # may be NULL in db
         description="Na místo se lze odkazovat kódem z písmen a číslic."
     )
     type = wtforms.SelectField(
         'Typ', choices=db.PlaceType.choices(), coerce=db.PlaceType.coerce
     )
-    nuts = wtforms.StringField(
+    nuts = mo_fields.String(
         'NUTS', filters=[lambda x: x or None],  # may be NULL in db
         description="Pro okresy a výše"
     )
-    note = wtforms.StringField('Poznámka')
+    note = mo_fields.String('Poznámka')
     submit = wtforms.SubmitField('Uložit')
 
 
 class PlaceSchoolEditForm(PlaceEditForm):
-    red_izo = wtforms.StringField('RED_IZO')
-    ico = wtforms.StringField('IČO')
-    official_name = wtforms.StringField('Oficiální název')
-    address = wtforms.StringField('Adresa')
+    red_izo = mo_fields.String('RED_IZO')
+    ico = mo_fields.String('IČO')
+    official_name = mo_fields.String('Oficiální název')
+    address = mo_fields.String('Adresa')
     is_zs = wtforms.BooleanField('ZŠ')
     is_ss = wtforms.BooleanField('SŠ')
     submit = wtforms.SubmitField('Uložit')
diff --git a/mo/web/org_round.py b/mo/web/org_round.py
index 26b1abcbe06744dc751d659405da991b8aa4835e..3aa42c34ec730a2f5356f9725cb3c6dd3babea80 100644
--- a/mo/web/org_round.py
+++ b/mo/web/org_round.py
@@ -279,11 +279,11 @@ def org_round(round_id: int, hier_id: Optional[int] = None):
 
 
 class TaskEditForm(FlaskForm):
-    code = wtforms.StringField('Kód úlohy', validators=[
+    code = mo_fields.String('Kód úlohy', validators=[
         validators.Required(),
         validators.Regexp(r'^[A-Za-z0-9-]+$', message="Kód úlohy smí obsahovat jen nediakritická písmena, čísla a znak -"),
     ], render_kw={'autofocus': True})
-    name = wtforms.StringField('Název úlohy')
+    name = mo_fields.String('Název úlohy')
     type = wtforms.SelectField('Typ úlohy', choices=db.TaskType.choices(), coerce=db.TaskType.coerce)
     max_points = mo_fields.Points(
         'Maximum bodů', validators=[validators.Optional(), validators.NumberRange(min=0)],
@@ -368,8 +368,8 @@ def org_round_task_edit(round_id: int, task_id: int):
 class RoundEditForm(FlaskForm):
     _for_round: Optional[db.Round] = None
 
-    name = wtforms.StringField("Název", render_kw={'autofocus': True})
-    code = wtforms.StringField("Kód",
+    name = mo_fields.String("Název", render_kw={'autofocus': True})
+    code = mo_fields.String("Kód",
         description="Kód kola používaný v kódech úloh ('1', 'S' apod.). Není-li vyplněn, použije se pořadí kola v kategorii.",
     )
     state = wtforms.SelectField(
@@ -396,7 +396,7 @@ class RoundEditForm(FlaskForm):
         description="Ovlivňuje možnost zadávání nových bodů, již uložené body nezmění"
     )
     enroll_mode = wtforms.SelectField("Režim přihlašování", choices=db.RoundEnrollMode.choices(), coerce=db.RoundEnrollMode.coerce)
-    enroll_advert = wtforms.StringField("Popis v přihlášce")
+    enroll_advert = mo_fields.String("Popis v přihlášce")
     has_messages = wtforms.BooleanField("Zprávičky pro účastníky (aktivuje možnost vytvářet novinky zobrazované účastníkům)")
     submit = wtforms.SubmitField('Uložit')
 
@@ -546,7 +546,7 @@ def org_edit_statement(round_id: int):
 
 
 class MessageAddForm(FlaskForm):
-    title = wtforms.StringField('Nadpis', validators=[validators.Required()])
+    title = mo_fields.String('Nadpis', validators=[validators.Required()])
     markdown = wtforms.TextAreaField(
         'Text zprávičky', description='Zprávičky lze formátovat pomocí Markdownu',
         validators=[validators.Required()],
diff --git a/mo/web/org_users.py b/mo/web/org_users.py
index 6d276fa9fd5e89ab836c94c63a792a6c4bf97994..956362a84b98dfcba3d77a18eb6b213a10973325 100644
--- a/mo/web/org_users.py
+++ b/mo/web/org_users.py
@@ -27,8 +27,8 @@ from mo.web.util import PagerForm
 
 class UsersFilterForm(PagerForm):
     # user
-    search_name = wtforms.TextField("Jméno/příjmení", render_kw={'autofocus': True})
-    search_email = wtforms.TextField("E-mail")
+    search_name = mo_fields.String("Jméno/příjmení", render_kw={'autofocus': True})
+    search_email = mo_fields.String("E-mail")
 
     # participants
     year = mo_fields.OptionalInt("Ročník")
@@ -132,15 +132,15 @@ def org_users():
 
 class OrgsFilterForm(PagerForm):
     # user
-    search_name = wtforms.TextField("Jméno/příjmení", render_kw={'autofocus': True})
-    search_email = wtforms.TextField("E-mail")
+    search_name = mo_fields.String("Jméno/příjmení", render_kw={'autofocus': True})
+    search_email = mo_fields.String("E-mail")
 
     search_role = wtforms.SelectMultipleField('Role', choices=db.RoleType.choices(), coerce=db.RoleType.coerce, validators=[validators.Optional()])
     search_right_for_place = mo_fields.Place('Právo pro oblast', validators=[validators.Optional()])
     search_in_place = mo_fields.Place('V oblasti', validators=[validators.Optional()])
     search_place_level = wtforms.SelectMultipleField("Úroveň oblasti", choices=[(i.level, i.name) for i in db.place_levels], validators=[validators.Optional()], coerce=int)
     search_year = mo_fields.IntList('Ročník', validators=[validators.Optional()])
-    search_category = wtforms.StringField("Kategorie", validators=[validators.Optional()])
+    search_category = mo_fields.String("Kategorie", validators=[validators.Optional()])
     search_seq = mo_fields.IntList("Kolo", validators=[validators.Optional()])
 
     submit = wtforms.SubmitField("Filtrovat")
@@ -238,7 +238,7 @@ class FormAddRole(FlaskForm):
     role = wtforms.SelectField('Role', choices=db.RoleType.choices(), coerce=db.RoleType.coerce, render_kw={'autofocus': True})
     place = mo_fields.Place()
     year = wtforms.IntegerField('Ročník', validators=[validators.Optional()])
-    category = wtforms.StringField("Kategorie", validators=[validators.Length(max=2)], filters=[lambda x: x or None])
+    category = mo_fields.String("Kategorie", validators=[validators.Length(max=2)], filters=[lambda x: x or None])
     seq = wtforms.IntegerField("Kolo", render_kw={"placeholder": "Pořadí kola v kategorii"}, validators=[validators.Optional()])
 
     submit = wtforms.SubmitField('Přidat roli')
@@ -612,8 +612,8 @@ def org_user_participant_edit(user_id: int, year: int):
 class GlobalOrgsImportForm(ImportForm):
     allow_change_user_to_org = wtforms.BooleanField("Povolit převádění účastníků na organizátory")
     default_place = mo_fields.Place("Výchozí oblast (není-li v souboru uvedena)")
-    default_cat = wtforms.StringField("Výchozí kategorie (není-li v souboru uvedena)")
-    default_code = wtforms.StringField("Výchozí kód kola (není-li v souboru uveden)")
+    default_cat = mo_fields.String("Výchozí kategorie (není-li v souboru uvedena)")
+    default_code = mo_fields.String("Výchozí kód kola (není-li v souboru uveden)")
     only_this_year = wtforms.BooleanField("Omezit práva na aktuální ročník", default=True)