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!

55개의 좋아요

또한 데스크톱에서도 이미지가 화면의 일부 공간을 차지하는 경우, 실수로 호버를 할 수 있습니다.
호버하여 흐림을 해제하는 대신, 각 NSFW 이미지의 위나 아래에 "NSFW 이미지 보기"라는 버튼을 동적으로 추가하는 것은 어떨까요?

4개의 좋아요

krita-artists.org에서는 이 기능을 호버가 아닌 클릭으로 작동하도록 약간 수정했습니다. 하지만 프로필에서 사용하는 설정이 작동하지 않습니다. 사용자가 NSFW 콘텐츠 표시를 설정해 두었더라도 흐릿하게 처리된 콘텐츠가 표시됩니다. 이 문제를 해결하는 방법이 있을까요?

더 이상 첫 게시글(OP)을 수정할 수 없지만, 업데이트된 코드를 여기에 올립니다. ‘클릭 시’ 솔루션도 함께 공유해 주시겠어요?

<!-- 현재 사용자의 nsfw 설정을 body 태그에 추가 -->
<script type="text/discourse-plugin" version="0.8.7">

// https://meta.discourse.org/t/css-classes-for-group-membership-for-simplified-ui-mode/60838/2
if (window.jQuery) {
    window.jQuery(function ($) {

        let currentUser = api.getCurrentUser();
        
        if (currentUser) {
            api.container.lookup('store:main').find('user', currentUser.username).then((user) => {

                if (user.user_fields[2]) {
                    $('body').addClass('nsfw-always-show' );
                }
            });
        }
    });
};
</script>
2개의 좋아요

우리의 onclick 솔루션은 다소 엉성하고 이상적이지 않을 수 있다고 생각합니다. 단순히 hover 시 블러를 제거하고 기본적으로 블러를 추가하는 방식으로 구현했습니다. 메시지도 사용자가 게시물을 보려면 클릭해야 한다는 내용으로 변경했습니다. 이제 사용자는 게시물을 보려면 한 번 클릭하고, lightbox에서 NSFW 이미지를 보려면 다시 한 번 클릭해야 합니다. 다소 번거롭지만, 의도치 않은 hover와 이미지 노출을 방지할 수 있습니다. 클릭 시 JS를 사용하여 블러를 제거하는 것이 더 나을 수도 있습니다.

/* #nswf 토픽의 모든 미디어에 NSFW 블러와 오버레이 텍스트 표시 */
.tag-nsfw { 
.topic-thumbnail {
    overflow:hidden;
}

	.topic-body .cooked .lightbox img, 
	.topic-body .cooked iframe, 
	.topic-body .cooked .lazyYT-container, 
	.topic-thumbnail img {
    filter: blur(30px);	
    -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: '⚠️ 성인 콘텐츠 - 이미지를 보려면 클릭하세요';
    background: #000;

	}
	
	.topic-body .cooked a.lightbox:before, 
	.topic-body .cooked iframe:before {
    top: 50%;
    left: 10px;
    right: 10px;
    text-align:center;
	}

	.topic-thumbnail a:before {
    top: 65px;
    left: 20px;
	}
	
}

/* 가입 폼에서 사용자 정의 필드 숨기기 */
.login-form .user-fields {display:none;}

/* 설정에서 이를 활성화한 사용자에게 NSFW 블러 비활성화 */
.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;
	}
}

@bartv @Terrapop

누군가 이 일을 맡고 싶다면, Discourse Image Filter 을 사용해 자동 NSFW 흐림 플러그인을 만들 수 있습니다.

4개의 좋아요

안녕하세요, 흐림 효과를 제거하고 대신 텍스트를 하이퍼링크로 만들고 싶습니다. 외부 기부 사이트로 연결되도록 하려고 하는데요, 어떻게 해야 할까요?

1개의 좋아요

아쉽게도 CSS만으로는 그런 것을 할 수 없어요. 그 기능을 구현하려면 직접 코드를 추가해야 합니다.

2개의 좋아요

CSS에서 filter: blur(10px); 줄만 삭제하면 됩니다.

5개의 좋아요

@bartv 첫 번째 게시물을 위키로 만들었습니다. 필요에 따라 자유롭게 수정해 주세요! :folded_hands:

10개의 좋아요