The `user-select: none` property displays distinct behavior in Safari

My Goal

I am in the process of creating an input-like content editable div. The idea is to click on tags outside the div and insert them inside the div while still being able to type around these tags.

The Issue and Reproduction Steps

To prevent tag buttons from being selected, I'm using user-select: none (normal and webkit). This works fine in Firefox and Chrome but not in Safari. I've tried adding the -webkit- prefix without success.

Here is a fiddle where you can see the problem in action.

Attempts Made

The main issue was maintaining the caret's position when leaving the content editable div.

I previously experimented with rangy but encountered limitations, especially in Firefox, which had negative effects on UX. You can reference my previous question that led me to explore the user-select: none solution here: Caret disappears in Firefox when saving its position with Rangy

This is how I arrived at the current solution utilizing user-select: none.

Components/JS:

// Vue initialization
new Vue({
  el: "#app",
        data(){
            return {
                // Data properties
            }
        },
        name: 'boolean-input',
        methods: {
            // Methods go here
        },
        props: [ 'first'],
        mounted() {
            this.addPlaceholder()
        }
})

HTML Structure:

<div id="app">
        <!-- HTML structure here -->
</div>

CSS Styling:

    /* CSS styles go here */

Note: Ignore the new Vue initialization code as it's copied from the fiddle link provided for inspection.

Expected Outcome vs Actual Results

In Safari, when clicking a tag after typing a word and moving the caret within that word, the tag should be inserted where the selection was made, but instead, it always gets added at the beginning of the content editable div.

In short, Safari doesn't maintain the caret's position when adding tags, resulting in the tag being placed at the start of the div rather than where the caret was located.

Edit 1: Upon investigation using getSelection(), it seems the offset is consistently 0 due to the div losing focus in Safari.

Answer №1

It appears that you have already come across the answer by yourself. The issue at hand seems to be related to timing.

If you switch the event to mousedown, you will notice that the caret position remains intact and the tag is inserted in the appropriate location.

<div id="app">
<div class="input__label-wrap">
<span class="input__label">Search</span>
<div style="user-select: none; -webkit-user-select: none">
<span readonly v-on:mousedown="addBooleanTag(b_button)" v-for="b_button in boolean_buttons" class="boolean-buttons">{{b_button.label}}</span>
</div>
</div> 
<div class="input__boolean input__boolean--no-focus">
<div 
@keydown.enter.prevent
@blur="addPlaceholder"
@keyup="saveCursorLocation($event); fixDelete(); clearHtmlElem($event);"
@input="updateBooleanInput($event); clearHtmlElem($event);"
@paste="pasted"
v-on:click="clearPlaceholder(); saveCursorLocation($event);"
class="input__boolean-content"
ref="divInput"
contenteditable="true">Keywords, boolean search..</div>
</div>
</div>

https://jsfiddle.net/xmuzp20o/

If you prefer not to insert the actual tag on mousedown, consider saving the caret position during that event so that you still have the correct position for the click event.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Enhancing the alignment of div elements

Our objective is to have two divs aligned next to each other. Here is the HTML code: <div class="test1>Text 1</div> <div class="test2>Text 2</div> And here is the CSS code: .test1 { float: left; } .test2 { float: left; } ...

"Enhance your website with a backspace button using jquery - here's

Recently, I delved into the world of jQuery and decided to test my skills by creating a jQuery calculator. Everything worked perfectly except for the backspace button. This is what I tried: if (value === backspace) { $(input).val($(input).val().substring ...

Error occurs when attempting to change the color of a dynamically generated div, resulting in the message: "Type Error: Unable to assign a value to the property '

I'm facing an issue with my code where I have a parent div that loads with a random color, and upon clicking a button, it should create a new colored div inside. However, I keep encountering the following error: TypeError: Cannot set property ' ...

Learn the ins and outs of Ember.js with our comprehensive tutorial and guide. Discover solutions to common issues such as DS

Learning Ember has been a challenging experience for me. The guide I am using seems to be lacking important information that I need. I keep encountering two specific errors: Uncaught Error: Ember.State has been moved into a plugin: https://github.com/e ...

Does jQuery's click event not successfully hide an element on Internet Explorer?

In my dropdown menu, I have the following options: <div class="my_div"> <select name="selection" id="select_id"> <option value="0">A</option> <option value="5">B</option> ...

Is it possible to showcase the data from three or more PHP files on a single webpage?

I currently have three PHP files: pie.php, bar.php, and line.php. When each file is run individually, it displays a webpage with a pie chart, bar chart, or line graph respectively. However, running all three files opens up separate webpages for each graph. ...

What is the best way to get rid of a tooltip from a disabled button

I am facing an issue with my button that is disabled using ng-disabled. The problem is that the button still shows a tooltip even when it is disabled. I need to find a way to remove the tooltip when the button is disabled. Check out my Button ...

Customize button design with data from API request

I am currently working on a project to showcase the status of multiple servers within a cluster. To achieve this, I have established a status route in my web service that returns 'ok' if the server is functioning correctly and an error message if ...

Unlocking the secrets of integrating Vuex store with JavaScript/TypeScript modules: A comprehensive guide

I am working on a vue application and I have a query. How can I access the store from javascript/typescript modules files using import/export? For example, if I create an auth-module that exports state, actions, mutations: export const auth = { namesp ...

Difficulty with font rendering across different web browsers such as Firefox, Chrome, and Opera

Visit the following website: I have implemented font-face on my site: @font-face { font-family: 'SegoeUI'; src: url('{site_url}themes/site_themes/agile_records/fonts/segoeui.eot?') format('eot'), url(' ...

Styling Challenges with CSS/AngularJS Accordion in Footer

I want to create a page layout as shown below: +---------------------------+ | Auto-fill / v scrollable ^| | || | || | v| +---------------------------+ | Fixed [][][] ...

Tips for accessing the information received from an AJAX call

When making an AJAX post request for processed data from the database in the form of an array [value1, value2, value3,...,valueN], I aim to use it on a ChartJS object. Here is the AJAX Request: $(document).ready($.post('callMeForAJAX.jsp', func ...

JavaScript string manipulation function

Hey everyone, I need help finding a one-line solution in JavaScript to determine if a string contains a semicolon without using a loop. If anyone knows how to do this, please share your knowledge! ...

How can I prevent a child div from activating the hover effect on its parent div?

I am currently exploring how to create a child element with position: absolute that is placed outside of its parent element without triggering the parent's :hover effect. Despite the parent having a hover effect, the child elements will still activat ...

Implementing Angular with HTML progress bar for interactive client-side features

Exploring the integration of HTML built-in progress bars with Angular: <label for="file">File progress:</label> <progress id="file" max="100" value="70">30%</progress> I am curious about how ...

The CSS property input::-webkit-outer-spin-button adjusts the margin-left and is exclusively visible in Chrome browser

Strange things are happening... Let me share the code for my inputs: #sign_in input#submit { height: 56px; background-color: #88b805; font-weight: bold; text-decoration: none; padding: 5px 40px 5px 40px; /* top, right, bottom, left ...

"Combining Node.js, MongoDB, and Vue.js to create a dynamic dependent select dropdown: a step-by-step

Seeking guidance on setting up a dynamic dependent dropdown list using node js, mongoDB and Vue js. As a newcomer to this concept, I'm unsure where to begin. Here is the scenario I am facing: I need assistance in creating 2 dropdown menus for country ...

Problem with organizing data by dates

My timers list looks like this: timer 1 => { startDate = 17/01/2019 11PM, endDate = 18/01/2019 9AM } timer 2 => { startDate = 18/01/2019 7AM, endDate = 18/01/2019 1PM } timer 3 => { startDate = 18/01/2019 12PM, endDate = 18/01/2019 10PM } time ...

Error encountered while attempting to download PDF file (blob) using JavaScript

Recently, I have been utilizing a method to download PDF files from the server using Laravel 8 (API Sanctum) and Vue 3. In my Vue component, I have implemented a function that allows for file downloads. const onDownloadDocument = (id) => { ...

Moving smoothly while retaining absolute positioning

I have a question about a particular scenario. I have a div element that is styled like a ball and I want it to transition diagonally across the page to the bottom right corner instead of moving suddenly. However, this is not happening as expected. Can you ...