2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

お題は不問!Qiita Engineer Festa 2023で記事投稿!

FlaskのWTFormsで作成したフォームにCSSを適用させたい!

Posted at

はじめに

FlaskのWTFormsでフォームを作成するとCSRF対策が簡単にできるため便利。
ただ、元のフォームは見栄えがシンプルすぎるのでCSSを適用させよう!という記事です。

初期段階

画面

元のフォーム.png

ソースコード

forms.py
class CreateVoiceForm(FlaskForm):
    title = StringField('タイトル: ', validators=[DataRequired()])
    voice = TextAreaField('内容: ', validators=[DataRequired()])
    picture_path = FileField('ファイルアップロード', default='')
    submit = SubmitField('ボイス投稿')
index.html
<form method="POST" enctype="multipart/form-data">
    {{ form.csrf_token }}
    {{ render_field(form.title) }}
    {{ render_field(form.voice) }}
    {{ render_field(form.picture_path) }}
    {{ form.submit() }}
</form>

結論

  • {{ render_field(form.title) }}は初期状態で<input id="title" name="title" type="text" value="">となっているため、idを指定してCSSを適用する
  • placeholderなどは、フォームを定義している箇所でrender_kw= を使用してレンダリングキーワードを設定する
    • 例)title = StringField('', validators=[DataRequired()], render_kw={"placeholder": "タイトルを入力"})

適用例

https://form.run/media/contents/form-creation-tools/contact-form_design/
こちらの記事を参考に、自分で少しいじってみました。

画面

変更フォーム.png

ソースコード

forms.py
class CreateVoiceForm(FlaskForm):
    title = StringField('', validators=[DataRequired()], render_kw={"placeholder": "タイトルを入力"})
    voice = TextAreaField('', validators=[DataRequired()], render_kw={"placeholder": "本文を入力"})
    picture_path = FileField('', default='')
    submit = SubmitField('ボイス投稿')
index.html
<form method="POST" enctype="multipart/form-data">
        {{ form.csrf_token }}
        <div class="form_item">
            <p class="form_item_label">
                <span class="form_item_label_required">必須</span>タイトル
            </p>
            {{ render_field(form.title) }}
        </div>
        <div class="form_item">
            <p class="form_item_label">
                <span class="form_item_label_required">必須</span>本文
            </p>
            {{ render_field(form.voice) }}
        </div>
        <div class="form_item">
            <p class="form_item_label">
                画像
            </p>
            {{ render_field(form.picture_path) }}
        </div>
        <div class="form_item_btn">
            {{ form.submit(class_="form_btn") }}
        </div>
    </form>
style.css
.form_item {
    border-top: 1px solid #ddd;
    padding-top: 24px;
    padding-bottom: 24px;
    width: 100%;
    display: flex;
    flex-flow: column;
}

@media screen and (max-width: 480px) {
    .form_item {
        padding-left: 14px;
        padding-right: 14px;
        padding-top: 16px;
        padding-bottom: 16px;
        flex-flow: column;
        flex-wrap: wrap;
    }
}

.form_item:nth-child(5) {
    border-bottom: 1px solid #ddd;
}

.form_item_label {
    width: 100%;
    max-width: 248px;
    letter-spacing: 0.05em;
    font-weight: bold;
    font-size: 22px;
}

@media screen and (max-width: 480px) {
    .form_item_label {
        max-width: inherit;
        display: flex;
        margin-left: 2em;
        align-items: center;
        font-size: 15px;
    }
}

.form_item_label_required {
    border-radius: 6px;
    margin-right: 8px;
    margin-bottom: 8px;
    padding-top: 8px;
    padding-bottom: 6px;
    width: 48px;
    display: inline-block;
    text-align: center;
    background: #FFCC66;
    color: #fff;
    font-size: 14px;
}

@media screen and (max-width: 480px) {
    .form_item_label_required {
        border-radius: 4px;
        padding-top: 4px;
        padding-bottom: 4px;
        width: 32px;
        font-size: 10px;
    }
}

button, input, textarea {
    font-family: Meiryo;
    font-size: 100%;
}

#title {
    border: 1px solid #ddd;
    border-radius: 6px;
    padding-left: 1em;
    padding-right: 1em;
    height: 48px;
    flex: 1;
    width: 100%;
    max-width: 410px;
    background: #eaedf2;
    font-size: 18px;
}

@media screen and (max-width: 480px) {
    #title {
        margin-left: 0;
        margin-top: 18px;
        height: 40px;
        flex: inherit;
        font-size: 15px;
    }
}

#voice {
    border: 1px solid #ddd;
    border-radius: 6px;
    padding-left: 1em;
    padding-right: 1em;
    height: 216px;
    flex: 1;
    width: 100%;
    max-width: 410px;
    background: #eaedf2;
    font-size: 18px;
}

@media screen and (max-width: 480px) {
    #voice {
        margin-top: 18px;
        margin-left: 0;
        height: 200px;
        flex: inherit;
        font-size: 15px;
    }
}

.form_item_btn {
    border-top: 1px solid #ddd;
}

.form_btn {
    border-radius: 6px;
    margin-top: 32px;
    margin-left: 100px;
    padding-top: 20px;
    padding-bottom: 20px;
    width: 200px;
    display: block;
    letter-spacing: 0.05em;
    background: #FFCC66;
    color: #fff;
    font-weight: bold;
    font-size: 20px;
}

最後に

初心者ながらに、色々試行錯誤してみました。
テキスト入力フィールドは出来たのですが、input type="file"のフォームをいじるとかなりめんどくさそう?だったので、今回は何もしていません。
しかし、余力のある人であれば挑戦してみると良いかと思います。(出来れば教えて頂きたいです。)

最後までご覧いただき、ありがとうございました。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?