XF 2.0 Customising the post template

Hi, my coder is having a bit of of a struggle changing the layout of the post template.

We can sort the CSS no problem and believe the template we need to change is 'post_macro' but we are a bit stuck.

If you have a look at the top image, this is what we are trying to achieve, the lower pic is what we currently have.

We need to:
  1. Make Avatar div wider (200px)
  2. Move name and user group above the avatar
  3. Make the Avatar landscape (186px wide by the ratio height)
  4. Move date and post # div to across the top
  5. Move the post options div to across the bottom
 

Attachments

  • post.webp
    post.webp
    48.7 KB · Views: 212
1.) Style properties -> message user info block width: 200px
2.) Edit: message_macros and move the username title above the avatar code
3.) This is a little weird, XF has fixed avatar sizes, s/m/l, you can edit the size in the message_macros template
4.) Replace post_macros with:

Code:
<xf:macro name="post" arg-post="!" arg-thread="!">
    <xf:css src="message.less" />
    <xf:set var="$isIgnored" value="{{ $post.isIgnored() }}" />
    <article class="message message--post js-post js-inlineModContainer {{ $isIgnored ? 'is-ignored' : '' }} {{ $post.isUnread() ? ' is-unread' : '' }}"
        data-author="{{ $post.User.username ?: $post.username }}"
        data-content="post-{$post.post_id}"
        id="js-post-{$post.post_id}">

        <span class="u-anchorTarget" id="post-{$post.post_id}"></span>

                    <header class="message-attribution">
                        <a href="{{ link('threads/post', $thread, {'post_id': $post.post_id}) }}" class="message-attribution-main u-concealed" rel="nofollow"><xf:date time="{$post.post_date}" /></a>
                        <div class="message-attribution-opposite">
                            <xf:if is="$post.isUnread()">
                                <span class="message-newIndicator">{{ phrase('new') }}</span>
                            </xf:if>
                            <a href="{{ link('threads/post', $thread, {'post_id': $post.post_id}) }}" class="u-concealed" rel="nofollow">#{{ number($post.position + 1) }}</a>
                        </div>
                    </header>
        
        <div class="message-inner">
            <div class="message-cell message-cell--user">
                <xf:set var="$dateHtml"><a href="{{ link('threads/post', $thread, {'post_id': $post.post_id}) }}" class="u-concealed" rel="nofollow"><xf:date time="{$post.post_date}" /></a></xf:set>
                <xf:set var="$linkHtml"><a href="{{ link('threads/post', $thread, {'post_id': $post.post_id}) }}" class="u-concealed" rel="nofollow">#{{ number($post.position + 1) }}</a></xf:set>
                <xf:macro template="message_macros" name="user_info" arg-user="{$post.User}" arg-fallbackName="{$post.username}" arg-dateHtml="{$dateHtml}" arg-linkHtml="{$linkHtml}" />
            </div>
            <div class="message-cell message-cell--main">
                <div class="message-main js-quickEditTarget">



                    <div class="message-content js-messageContent">

                        <xf:if is="$post.message_state == 'deleted'">
                            <div class="messageNotice messageNotice--deleted">
                                <xf:macro template="deletion_macros" name="notice" arg-log="{$post.DeletionLog}" />
                            </div>
                        <xf:elseif is="$post.message_state == 'moderated'" />
                            <div class="messageNotice messageNotice--moderated">
                                {{ phrase('this_message_is_awaiting_moderator_approval_and_is_invisible_to_normal') }}
                            </div>
                        </xf:if>
                        <xf:if is="$post.warning_message">
                            <div class="messageNotice messageNotice--warning">
                                {$post.warning_message}
                            </div>
                        </xf:if>
                        <xf:if is="$isIgnored">
                            <div class="messageNotice messageNotice--ignored">
                                {{ phrase('you_are_ignoring_content_by_this_member') }}
                                <xf:showignored />
                            </div>
                        </xf:if>

                        <div class="message-userContent lbContainer js-lbContainer {{ $isIgnored ? 'is-ignored' : '' }}"
                            data-lb-id="post-{$post.post_id}"
                            data-lb-caption-desc="{{ $post.User ? $post.User.username : $post.username }} &middot; {{ date_time($post.post_date) }}">

                            <xf:if is="$post.isFirstPost()">
                                <xf:macro template="custom_fields_macros" name="custom_fields_view"
                                    arg-type="threads"
                                    arg-group="before"
                                    arg-onlyInclude="{$thread.Forum.field_cache}"
                                    arg-set="{$thread.custom_fields}"
                                    arg-wrapperClass="message-fields message-fields--before" />
                            </xf:if>

                            <article class="message-body js-selectToQuote">
                                <xf:ad position="post_above_content" arg-post="{$post}" />
                                {{ bb_code($post.message, 'post', $post) }}
                                <div class="js-selectToQuoteEnd">&nbsp;</div>
                                <xf:ad position="post_below_content" arg-post="{$post}" />
                            </article>

                            <xf:if is="$post.isFirstPost()">
                                <xf:macro template="custom_fields_macros" name="custom_fields_view"
                                    arg-type="threads"
                                    arg-group="after"
                                    arg-onlyInclude="{$thread.Forum.field_cache}"
                                    arg-set="{$thread.custom_fields}"
                                    arg-wrapperClass="message-fields message-fields--after" />
                            </xf:if>

                            <xf:if is="$post.attach_count">
                                <xf:macro template="message_macros" name="attachments"
                                    arg-attachments="{$post.Attachments}"
                                    arg-message="{$post}"
                                    arg-canView="{{ $thread.canViewAttachments() }}" />
                            </xf:if>
                        </div>

                        <xf:if is="$post.last_edit_date">
                            <div class="message-lastEdit">
                                <xf:if is="$post.user_id == $post.last_edit_user_id">
                                    {{ phrase('last_edited:') }} <xf:date time="{$post.last_edit_date}" />
                                <xf:else />
                                    {{ phrase('last_edited_by_moderator:') }} <xf:date time="{$post.last_edit_date}" />
                                </xf:if>
                            </div>
                        </xf:if>

                        <xf:macro template="message_macros" name="signature" arg-user="{$post.User}" />
                    </div>
                    
                        <div class="likesBar js-likeList {{ $post.likes ? 'is-active' : '' }}">
                            <xf:likes content="{$post}" url="{{ link('posts/likes', $post) }}" />
                        </div>

                        <div class="js-historyTarget message-historyTarget toggleTarget" data-href="trigger-href"></div>


                </div>
            </div>
        </div>
                    <footer class="message-footer">
                        <xf:if contentcheck="true">
                            <div class="message-actionBar actionBar">
                                <xf:contentcheck>
                                    <xf:if contentcheck="true">
                                        <div class="actionBar-set actionBar-set--external">
                                        <xf:contentcheck>
                                            <xf:if is="$post.canLike()">
                                                <a href="{{ link('posts/like', $post) }}" class="actionBar-action actionBar-action--like" data-xf-click="like" data-like-list="< .js-post | .js-likeList"><xf:if is="$post.isLiked()">{{ phrase('unlike') }}<xf:else />{{ phrase('like') }}</xf:if></a>
                                            </xf:if>
                                            <xf:if is="$thread.canReply()">
                                                <xf:set var="$quoteLink">{{ link('threads/reply', $thread, {'quote': $post.post_id}) }}</xf:set>

                                                <xf:if is="$xf.options.multiQuote">
                                                    <a href="{$quoteLink}"
                                                        class="actionBar-action actionBar-action--mq u-jsOnly js-multiQuote"
                                                        title="{{ phrase('toggle_multi_quote_tooltip')|for_attr }}"
                                                        data-message-id="{$post.post_id}"
                                                        data-mq-action="add">{{ phrase('quote') }}</a>
                                                </xf:if>

                                                <a href="{$quoteLink}"
                                                    class="actionBar-action actionBar-action--reply"
                                                    title="{{ phrase('reply_quoting_this_message')|for_attr }}"
                                                    data-xf-click="quote"
                                                    data-quote-href="{{ link('posts/quote', $post) }}">{{ phrase('reply') }}</a>
                                            </xf:if>
                                        </xf:contentcheck>
                                        </div>
                                    </xf:if>

                                    <xf:if contentcheck="true">
                                        <div class="actionBar-set actionBar-set--internal">
                                        <xf:contentcheck>
                                            <xf:if is="$post.canUseInlineModeration()">
                                                <span class="actionBar-action actionBar-action--inlineMod">
                                                    <xf:checkbox standalone="true">
                                                        <xf:option value="{$post.post_id}" class="js-inlineModToggle"
                                                            data-xf-init="tooltip"
                                                            title="{{ phrase('select_for_moderation')|for_attr }}"
                                                            label="{{ phrase('select_for_moderation') }}"
                                                            hiddenlabel="true" />
                                                    </xf:checkbox>
                                                </span>
                                            </xf:if>

                                            <xf:if is="$post.canReport()">
                                                <a href="{{ link('posts/report', $post) }}"
                                                    class="actionBar-action actionBar-action--report"
                                                    data-xf-click="overlay">{{ phrase('report') }}</a>
                                            </xf:if>

                                            <xf:set var="$hasActionBarMenu" value="{{ false }}" />
                                            <xf:if is="$post.canEdit()">
                                                <xf:js src="xf/message.js" min="1" />
                                                <a href="{{ link('posts/edit', $post) }}"
                                                    class="actionBar-action actionBar-action--edit actionBar-action--menuItem"
                                                    data-xf-click="quick-edit"
                                                    data-editor-target="#js-post-{$post.post_id} .js-quickEditTarget"
                                                    data-menu-closer="true">{{ phrase('edit') }}</a>

                                                <xf:set var="$hasActionBarMenu" value="{{ true }}" />
                                            </xf:if>
                                            <xf:if is="$post.edit_count && $post.canViewHistory()">
                                                <a href="{{ link('posts/history', $post) }}"
                                                    class="actionBar-action actionBar-action--history actionBar-action--menuItem"
                                                    data-xf-click="toggle"
                                                    data-target="#js-post-{$post.post_id} .js-historyTarget"
                                                    data-menu-closer="true">{{ phrase('history') }}</a>

                                                <xf:set var="$hasActionBarMenu" value="{{ true }}" />
                                            </xf:if>
                                            <xf:if is="$post.canDelete('soft')">
                                                <a href="{{ link('posts/delete', $post) }}"
                                                    class="actionBar-action actionBar-action--delete actionBar-action--menuItem"
                                                    data-xf-click="overlay">{{ phrase('delete') }}</a>

                                                <xf:set var="$hasActionBarMenu" value="{{ true }}" />
                                            </xf:if>
                                            <xf:if is="$post.canCleanSpam()">
                                                <a href="{{ link('spam-cleaner', $post) }}"
                                                    class="actionBar-action actionBar-action--spam actionBar-action--menuItem"
                                                    data-xf-click="overlay">{{ phrase('spam') }}</a>

                                                <xf:set var="$hasActionBarMenu" value="{{ true }}" />
                                            </xf:if>
                                            <xf:if is="$xf.visitor.canViewIps() && $post.ip_id">
                                                <a href="{{ link('posts/ip', $post) }}"
                                                    class="actionBar-action actionBar-action--ip actionBar-action--menuItem"
                                                    data-xf-click="overlay">{{ phrase('ip') }}</a>

                                                <xf:set var="$hasActionBarMenu" value="{{ true }}" />
                                            </xf:if>
                                            <xf:if is="$post.canWarn()">

                                                <a href="{{ link('posts/warn', $post) }}"
                                                    class="actionBar-action actionBar-action--warn actionBar-action--menuItem">{{ phrase('warn') }}</a>

                                                <xf:set var="$hasActionBarMenu" value="{{ true }}" />
                                            <xf:elseif is="$post.warning_id && $xf.visitor.canViewWarnings()" />
                                                <a href="{{ link('warnings', {'warning_id': $post.warning_id}) }}"
                                                    class="actionBar-action actionBar-action--warn actionBar-action--menuItem"
                                                    data-xf-click="overlay">{{ phrase('view_warning') }}</a>
                                                <xf:set var="$hasActionBarMenu" value="{{ true }}" />
                                            </xf:if>

                                            <xf:if is="$hasActionBarMenu">
                                                <a class="actionBar-action actionBar-action--menuTrigger"
                                                    data-xf-click="menu"
                                                    title="{{ phrase('more_options')|for_attr }}"
                                                    role="button"
                                                    tabindex="0"
                                                    aria-expanded="false"
                                                    aria-haspopup="true">&#8226;&#8226;&#8226;</a>

                                                <div class="menu" data-menu="menu" aria-hidden="true" data-menu-builder="actionBar">
                                                    <div class="menu-content">
                                                        <h4 class="menu-header">{{ phrase('more_options') }}</h4>
                                                        <div class="js-menuBuilderTarget"></div>
                                                    </div>
                                                </div>
                                            </xf:if>
                                        </xf:contentcheck>
                                        </div>
                                    </xf:if>

                                </xf:contentcheck>
                            </div>
                        </xf:if>
                    </footer>
    </article>

    <xf:ad position="post_below_container" arg-post="{$post}" />
</xf:macro>

<xf:macro name="post_deleted" arg-post="!" arg-thread="!">
    <xf:css src="message.less" />
    <div class="message message--deleted message--post{{ $post.isIgnored() ? ' is-ignored' : '' }}{{ $post.isUnread() ? ' is-unread' : '' }} js-post js-inlineModContainer"
        data-author="{{ $post.User.username ?: $post.username }}"
        data-content="post-{$post.post_id}">

        <span class="u-anchorTarget" id="post-{$post.post_id}"></span>
        <div class="message-inner">
            <div class="message-cell message-cell--user">
                <xf:macro template="message_macros" name="user_info" arg-user="{$post.User}" arg-fallbackName="{$post.username}" />
            </div>
            <div class="message-cell message-cell--main">
                <div class="message-attribution">
                    <ul class="listInline listInline--bullet message-attribution-main">
                        <li><a href="{{ link('threads/post', $thread, {'post_id': $post.post_id}) }}" class="u-concealed" rel="nofollow"><xf:date time="{$post.post_date}" /></a></li>
                        <li><xf:username user="{$post.User}" defaultname="{$post.username}" class="u-concealed" /></li>
                    </ul>
                </div>

                <div class="messageNotice messageNotice--deleted">
                    <xf:macro template="deletion_macros" name="notice" arg-log="{$post.DeletionLog}" />

                    <a href="{{ link('posts/show', $post) }}" class="u-jsOnly" data-xf-click="inserter" data-replace="[data-content=post-{$post.post_id}]">{{ phrase('show...') }}</a>
                </div>
            </div>
        </div>
    </div>

    <xf:ad position="post_below_container" arg-post="{$post}" />
</xf:macro>

Some styling in extra.less:

Code:
.message-attribution, .message-footer {
    padding: 10px;
    background-color: #e4e4e4;
    .message-actionBar .actionBar-set { margin-top: 0; }
}

The result (skipped 2 and 3):

Screenshot_16.webp
 
Top Bottom