Our solution for blurring NSFW content

At the Blender Artists forum we have a faily liberal content policy where we allow nudity and violence (up to a point). While most members are fine with this kind of content, there are of course audiences and situations where this is not suitable (for us mainly schools and children). And since we make heavy use of tiled galleries with the Topic List Preview plugin, we needed a way to make this kind of content opt-in and get it out of your face by default.

The solution was easier to implement than expected and I decided to share it here in case anyone else can use it. Fair warning: I’ll link to some NSFW content here. Let’s go!

We already required an #nsfw tag for any relevant posts and have been enforcing this strictly for the last few months. Our AdSense plugin is configured to not display ads on these pages as that will (and has!) get us into trouble with Google. (Big thanks to @neil for adding this feature!)

Using some CSS we added a blur and overlay text for all media inside such topics. The blur will be removed on hover:

/* display nsfw blur and overlay text on any media in #nswf topics */
.tag-nsfw { 
	.topic-body .cooked img, 
	.topic-body .cooked iframe, 
	.topic-body .cooked .lazyYT-container, 
	.topic-thumbnail img {
        filter: blur(10px);	
        -webkit-transition: .3s ease-in-out;
        transition: .2s ease-in-out;
	}

	.topic-body:hover .cooked img, 
	.topic-body:hover .cooked iframe,
	.topic-body:hover .cooked .lazyYT-container, 		
	.topic-thumbnail:hover img {
        filter: blur(0);	
        -webkit-transition: .3s ease-in-out;
        transition: .2s ease-in-out;
	}

	.topic-body .cooked a.lightbox:before, 
	.topic-body .cooked iframe:before,
	.topic-thumbnail a:before {
	    z-index:2;
        padding: 5px;
        font-size:1em;
        position:absolute;

        color:#fff;
        content: '⚠️ Mature content - Hover to show';
        background: #e86800;

	}
	
	.topic-body .cooked a.lightbox:before, 
	.topic-body .cooked iframe:before {
        top: 15px;
        left: 10px;
	}

	.topic-thumbnail a:before {
        top: 65px;
        left: 20px;
	}
	
	.topic-body .cooked a.lightbox:hover:before, 
	.topic-body .cooked iframe:hover:before,
	.topic-thumbnail a:hover:before {		
	    display:none;
	}
}

Images and videos in a topic now look like this:

And in any TLP tiled galleries, we have:

Next, we added a preference that allows users to disable the blurring for their account. This turned out to be easier to implement than I thought using custom fields.

We started by creating a checkbox custom field:

Then, we repurposed some code to add ‘nsfw-always-show’ tag to the body class for these users:

<!-- add current user's nsfw preferences to body tag -->
<script type="text/discourse-plugin" version="0.8">

// https://meta.discourse.org/t/css-classes-for-group-membership-for-simplified-ui-mode/60838/2
if (window.jQuery) {
    window.jQuery(function ($) {
        var u = Discourse.User.current();

        // always show NSFW
        if (u.custom_fields.user_field_2) {
            console.log('show nsfw for user');
            $('body').addClass('nsfw-always-show' );
        }

    });
};

</script>

A last bit of CSS removes the blurring for these users:

/* hide custom fields from signup form */

.login-form .user-fields {display:none;}

/* disable nsfw blurring for users who set this in their preferences */

.nsfw-always-show .tag-nsfw {
	.topic-body .cooked img, 
	.topic-body .cooked iframe, 
	.topic-body .cooked .lazyYT-container, 
	.topic-thumbnail img {
        filter: blur(0px);	
	}
	
	.topic-body .cooked a.lightbox:before, 
	.topic-body .cooked iframe:before,
	.topic-thumbnail a:before {
	    display:none;
	    content: none;
	}
}

A known issue with this approach is that it does not work great on mobile yet as :hover is not supported.

If you want to see this in action you can visit our #nsfw tag page, but, well, you might see some nsfw content there :slight_smile:

I hope this was useful for someone!

25 Likes