Profile Banner and Avatar

I agree, I'd like to see an option where you can keep everything seperate from overlapping

It might look okay if you have a nice abstract background. But as soon as you start putting actual photos up it starts to get messy looking and you can't appreciate the banner in full, or easily read the text, even with darkening the background and adding shadow etc.

Please add the option to instead keep everything separated like this

1595673706454.png
 
Part of my original suggestion, which I forgot to post was for this also to be the case for the membercard.

Have the banner on it's own as a banner above the avatar, username and user info. Not everything completely covering the banner as it is now which ends up crazy busy looking.
 
Or another option, at least add a border around the avatar. If you use the content background color, it makes the avatar "pop" a little better:

1605639416661.webp

This isn't fully tested yet, but this made it work for me:

Less:
/* Add border around member profile header avatar */
.memberHeader-avatar .avatarWrapper .avatar.avatar--l {
    border: 3px solid @xf-contentBg;
}

Even if we can't get the banner separated from the avatar and username block (that would be an option I would consider, being able to enable or disable it as needed), this at least tidies things up a little.
 
I was working on a site yesterday, upgraded to 2.2, turned this on and it looked pretty bad out of the box with all the default user info text overlays, shadows and strokes etc. when combined with the type of images they were uploading, so I just had to turn profile banners off completely for now as the client didn't like it, which was a shame.
 
It's a nice idea, but it could use a little finessing. The "busy avatar on busy background" does make it a bit jumbled, which is why I felt a border would break up that visual clash a little. I haven't decided what to do about the text yet, but I don't mind getting in and trying some template modifications to see what I can come up with.
 
It's a nice idea, but it could use a little finessing. The "busy avatar on busy background" does make it a bit jumbled, which is why I felt a border would break up that visual clash a little. I haven't decided what to do about the text yet, but I don't mind getting in and trying some template modifications to see what I can come up with.
Could wind up being a pretty cool addon.
 
Okay, here's a quick fix, not thoroughly tested, and there's probably a better way to rearrange the templates but I couldn't be faffed with the css this evening and this gets around changing any css, but if you add a template modification to find and replace this section of code from the member_view template it should work.

Find:

Code:
            <div class="memberHeader {{ $user.Profile.banner_date ? 'memberHeader--withBanner' : '' }}">
                <xf:profilebanner user="$user" size="l" class="memberHeader-main" toggle="memberHeader--withBanner">
                    <div class="memberHeader-mainContent">
                        <span class="memberHeader-avatar">
                            <span class="avatarWrapper">
                                <xf:avatar user="{$user}" size="l"
                                    href="{{ $user.getAvatarUrl('o') ?: '' }}" />
                                <xf:if is="$user.user_id == $xf.visitor.user_id && $xf.visitor.canUploadAvatar()">
                                    <a class="avatarWrapper-update" href="{{ link('account/avatar') }}" data-xf-click="overlay"><span>{{ phrase('edit') }}</span></a>
                                </xf:if>
                            </span>
                        </span>
                        <div class="memberHeader-content memberHeader-content--info">
                        <xf:if contentcheck="true">
                            <div class="memberHeader-actionTop">
                                <xf:contentcheck>
                                <!--[XF:action_top_start]-->
                                <xf:if contentcheck="true">
                                    <div class="buttonGroup">
                                        <xf:contentcheck>
                                            <xf:if is="$user.canBeReported()">
                                                <xf:button href="{{ link('members/report', $user) }}"
                                                    class="button--link" overlay="true">
                                                    {{ phrase('report_verb') }}
                                                </xf:button>
                                            </xf:if>
                                            <xf:if is="$user.user_id == $xf.visitor.user_id && $xf.visitor.canUploadProfileBanner()">
                                                <xf:button href="{{ link('account/banner') }}"
                                                    class="button--link" overlay="true">
                                                    {{ phrase('edit_profile_banner') }}
                                                </xf:button>
                                            </xf:if>
                                            <xf:if contentcheck="true">
                                                <div class="buttonGroup-buttonWrapper">
                                                    <xf:button class="button--link menuTrigger" data-xf-click="menu" aria-expanded="false" aria-haspopup="true">{{ phrase('moderator_tools') }}</xf:button>
                                                    <div class="menu" data-menu="menu" aria-hidden="true">
                                                        <div class="menu-content">
                                                            <h3 class="menu-header">{{ phrase('moderator_tools') }}</h3>
                                                            <xf:contentcheck>
                                                                <xf:macro template="member_macros" name="moderator_menu_actions"
                                                                    arg-user="{$user}"
                                                                    arg-context="profile" />
                                                            </xf:contentcheck>
                                                        </div>
                                                    </div>
                                                </div>
                                            </xf:if>
                                        </xf:contentcheck>
                                    </div>
                                </xf:if>
                                <!--[XF:action_top_end]-->
                                </xf:contentcheck>
                            </div>
                        </xf:if>

                        <h1 class="memberHeader-name">
                            <span class="memberHeader-nameWrapper" data-stroke="{$user.username}">
                                <xf:username user="{$user}" rich="true" href="" />
                            </span>
                            <xf:if is="$user.hasViewableUsernameHistory()">
                                <a class="memberHeader-nameChangeIndicator"
                                    data-xf-click="menu"
                                    data-xf-init="tooltip"
                                    title="{{ phrase('username_changed') }}"
                                    role="button"
                                    tabindex="0"
                                    aria-expanded="false"
                                    aria-haspopup="true"
                                    aria-label="{{ phrase('username_changed') }}"><xf:fa icon="fa-history" /></a>
                                <div class="menu" data-menu="menu" aria-hidden="true"
                                    data-href="{{ link('members/username-history', $user, {'menu': 1}) }}"
                                    data-load-target=".js-usernameHistoryBody">
                                    <div class="menu-content">
                                        <h3 class="menu-header">{{ phrase('previous_usernames') }}</h3>
                                        <div class="js-usernameHistoryBody">
                                            <div class="menu-row">
                                                {{ phrase('loading...') }}
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </xf:if>
                        </h1>

                        <xf:if contentcheck="true">
                            <div class="memberHeader-banners">
                                <xf:contentcheck><xf:userbanners user="$user" /></xf:contentcheck>
                            </div>
                        </xf:if>

                        <div class="memberHeader-blurbContainer">
                            <xf:userblurb user="$user" tag="div" class="memberHeader-blurb" />

                            <div class="memberHeader-blurb">
                                <dl class="pairs pairs--inline">
                                    <dt>{{ phrase('joined') }}</dt>
                                    <dd><xf:date time="$user.register_date" /></dd>
                                </dl>
                            </div>

                            <xf:if contentcheck="true">
                                <div class="memberHeader-blurb">
                                    <dl class="pairs pairs--inline">
                                        <dt>{{ phrase('last_seen') }}</dt>
                                        <dd dir="auto">
                                            <xf:contentcheck><xf:useractivity user="$user" class="pairs--plainLabel" /></xf:contentcheck>
                                        </dd>
                                    </dl>
                                </div>
                            </xf:if>
                        </div>
                    </div>
                    </div>
                </xf:profilebanner>

                <div class="memberHeader-content">
                    <div class="memberHeader-stats">
                        <div class="pairJustifier">
                            <xf:macro template="member_macros" name="member_stat_pairs"
                                arg-user="{$user}"
                                arg-context="profile" />
                        </div>
                    </div>

                    <xf:if contentcheck="true">
                        <hr class="memberHeader-separator" />

                        <div class="memberHeader-buttons">
                            <xf:contentcheck>
                                <xf:macro template="member_macros" name="member_action_buttons"
                                    arg-user="{$user}"
                                    arg-context="profile" />
                            </xf:contentcheck>
                        </div>
                    </xf:if>
                </div>

            </div>

And replace with:

Code:
            <div class="memberHeader {{ $user.Profile.banner_date ? 'memberHeader--withBanner' : '' }}">
                <xf:profilebanner user="$user" size="l" class="memberHeader-main" toggle="memberHeader--withBanner">
                </xf:profilebanner>
            </div>
            <div class="memberHeader-mainContent">
                <span class="memberHeader-avatar">
                    <span class="avatarWrapper">
                        <xf:avatar user="{$user}" size="l"
                            href="{{ $user.getAvatarUrl('o') ?: '' }}" />
                        <xf:if is="$user.user_id == $xf.visitor.user_id && $xf.visitor.canUploadAvatar()">
                            <a class="avatarWrapper-update" href="{{ link('account/avatar') }}" data-xf-click="overlay"><span>{{ phrase('edit') }}</span></a>
                        </xf:if>
                    </span>
                </span>
                <div class="memberHeader-content memberHeader-content--info">
                <xf:if contentcheck="true">
                    <div class="memberHeader-actionTop">
                        <xf:contentcheck>
                        <!--[XF:action_top_start]-->
                        <xf:if contentcheck="true">
                            <div class="buttonGroup">
                                <xf:contentcheck>
                                    <xf:if is="$user.canBeReported()">
                                        <xf:button href="{{ link('members/report', $user) }}"
                                            class="button--link" overlay="true">
                                            {{ phrase('report_verb') }}
                                        </xf:button>
                                    </xf:if>
                                    <xf:if is="$user.user_id == $xf.visitor.user_id && $xf.visitor.canUploadProfileBanner()">
                                        <xf:button href="{{ link('account/banner') }}"
                                            class="button--link" overlay="true">
                                            {{ phrase('edit_profile_banner') }}
                                        </xf:button>
                                    </xf:if>
                                    <xf:if contentcheck="true">
                                        <div class="buttonGroup-buttonWrapper">
                                            <xf:button class="button--link menuTrigger" data-xf-click="menu" aria-expanded="false" aria-haspopup="true">{{ phrase('moderator_tools') }}</xf:button>
                                            <div class="menu" data-menu="menu" aria-hidden="true">
                                                <div class="menu-content">
                                                    <h3 class="menu-header">{{ phrase('moderator_tools') }}</h3>
                                                    <xf:contentcheck>
                                                        <xf:macro template="member_macros" name="moderator_menu_actions"
                                                            arg-user="{$user}"
                                                            arg-context="profile" />
                                                    </xf:contentcheck>
                                                </div>
                                            </div>
                                        </div>
                                    </xf:if>
                                </xf:contentcheck>
                            </div>
                        </xf:if>
                        <!--[XF:action_top_end]-->
                        </xf:contentcheck>
                    </div>
                </xf:if>

                <h1 class="memberHeader-name">
                    <span class="memberHeader-nameWrapper" data-stroke="{$user.username}">
                        <xf:username user="{$user}" rich="true" href="" />
                    </span>
                    <xf:if is="$user.hasViewableUsernameHistory()">
                        <a class="memberHeader-nameChangeIndicator"
                            data-xf-click="menu"
                            data-xf-init="tooltip"
                            title="{{ phrase('username_changed') }}"
                            role="button"
                            tabindex="0"
                            aria-expanded="false"
                            aria-haspopup="true"
                            aria-label="{{ phrase('username_changed') }}"><xf:fa icon="fa-history" /></a>
                        <div class="menu" data-menu="menu" aria-hidden="true"
                            data-href="{{ link('members/username-history', $user, {'menu': 1}) }}"
                            data-load-target=".js-usernameHistoryBody">
                            <div class="menu-content">
                                <h3 class="menu-header">{{ phrase('previous_usernames') }}</h3>
                                <div class="js-usernameHistoryBody">
                                    <div class="menu-row">
                                        {{ phrase('loading...') }}
                                    </div>
                                </div>
                            </div>
                        </div>
                    </xf:if>
                </h1>

                <xf:if contentcheck="true">
                    <div class="memberHeader-banners">
                        <xf:contentcheck><xf:userbanners user="$user" /></xf:contentcheck>
                    </div>
                </xf:if>

                <div class="memberHeader-blurbContainer">
                    <xf:userblurb user="$user" tag="div" class="memberHeader-blurb" />

                    <div class="memberHeader-blurb">
                        <dl class="pairs pairs--inline">
                            <dt>{{ phrase('joined') }}</dt>
                            <dd><xf:date time="$user.register_date" /></dd>
                        </dl>
                    </div>

                    <xf:if contentcheck="true">
                        <div class="memberHeader-blurb">
                            <dl class="pairs pairs--inline">
                                <dt>{{ phrase('last_seen') }}</dt>
                                <dd dir="auto">
                                    <xf:contentcheck><xf:useractivity user="$user" class="pairs--plainLabel" /></xf:contentcheck>
                                </dd>
                            </dl>
                        </div>
                    </xf:if>
                </div>
            </div>
            </div>
            <div class="memberHeader-content">
                <div class="memberHeader-stats">
                    <div class="pairJustifier">
                        <xf:macro template="member_macros" name="member_stat_pairs"
                            arg-user="{$user}"
                            arg-context="profile" />
                    </div>
                </div>

                <xf:if contentcheck="true">
                    <hr class="memberHeader-separator" />

                    <div class="memberHeader-buttons">
                        <xf:contentcheck>
                            <xf:macro template="member_macros" name="member_action_buttons"
                                arg-user="{$user}"
                                arg-context="profile" />
                        </xf:contentcheck>
                    </div>
                </xf:if>
            </div>

Will change this:

1605650936845.webp


to this:

1605651025196.webp
 
Nice work @RobinHood :)

I've been using something similar, actually been using this same layout since XF 2.x when I used third-party profile "banner/header" addons.

Profile with banner
Screenshot_2020-11-17 Gemma.png

Profile without banner
Screenshot_2020-11-17 Gemma1.png

Member tooltip with banner
Untitled-1.png

Member tooltip without banner
Untitled-2.png

The banner/header looks much cleaner and, if you have wonky eyes like me, you can actually read the text.
 
Last edited:
Thanks :)

Yeah, need to sort the tooltip next.

I think I'd also like to have the option to auto adjust the height of the profile banner banner image so less or none of it gets cropped, which feels nice and high impact. I think I have an old user profile banner plugin on an XF1 site that does that, so might take a peek to see how they did it and try to re-apply it to the new system.
 
You’d likely be removing/replacing/moving too much code in the templates for an addon. You can only completely change templates via a style, not an addon as far as XF is concerned.
 
You’d likely be removing/replacing/moving too much code in the templates for an addon. You can only completely change templates via a style, not an addon as far as XF is concerned.
Would be something he would have to look out for that's certain. The challenge gauntlet drops!
 
I added lightbox triggers for the profile images to make them more immersive now that we have the fancy new lightbox. That way even if the cover photo gets cropped, visitors can still view the full size version.

Got a few issues to sort out with it to get it working properly, might release it as an add on after that.

To view this content we will need your consent to set third party cookies.
For more detailed information, see our cookies page.
 
Top Bottom