【问题标题】:No outline on mouse focus but still have outline on keyboard focus?鼠标焦点上没有轮廓,但键盘焦点上仍有轮廓?
【发布时间】:2013-08-02 17:34:27
【问题描述】:

当页面元素(例如链接或按钮)具有焦点时,它们会显示轮廓。我希望这个大纲仅在该元素被键盘而不是鼠标获得焦点时显示。

是否可以确定该元素是如何通过 JavaScript 获得焦点的?如果是这样,我该如何控制浏览器自己的大纲功能?

【问题讨论】:

  • 如果你不知道从哪里开始,你可以看看 CSS。仅将 css 添加到输入元素并查看它是如何工作的。之后,你可以做一些更花哨的事情,以你想要的方式工作。

标签: javascript jquery html css


【解决方案1】:

浏览器使用 CSS outline 属性来显示哪个元素具有焦点,您可能已经知道了。因此,在 jQuery 中,您可以使用:

$(document).ready(function() {
    $("body").on("mousedown", "*", function(e) {
        if (($(this).is(":focus") || $(this).is(e.target)) && $(this).css("outline-style") == "none") {
            $(this).css("outline", "none").on("blur", function() {
                $(this).off("blur").css("outline", "");
            });
        }
    });
});

解释:此函数查找任何元素上的mousedown 事件。此事件是委托的,这意味着它将应用于页面上当前的元素以及将来动态创建的任何元素。当鼠标在元素上单击时,其 CSS outline 属性设置为 none;轮廓被移除。

目标元素获得blur 的新处理程序。当从元素获得焦点时,outline 属性设置为空白字符串(这会将其从元素的style 属性中删除),从而允许浏览器再次控制轮廓。然后,该元素删除它自己的blur 处理程序以释放内存。这样,元素只有在从键盘获得焦点时才会被勾勒出来。

编辑

根据下面 Rakesh 的 cmets,我做了些许改动。该函数现在可以检测是否已经有一个 outline 集,并避免覆盖它。 Demo here.

【讨论】:

  • 按照我认为如果我的 html 中有一些元素在我使用大纲的地方,这段代码将永远删除它。
  • 你用我贴的小提琴测试了吗?因为blur 处理程序负责处理。当元素失去焦点时,它的outline 会被jQuery 的css() 的一个特殊功能移除。当设置为空白字符串时,CSS 属性将从元素的 style 属性中删除(如果存在)。由于元素的style 属性具有最高优先级,因此当从那里删除该属性时,其outline 将恢复到之前定义的位置。
  • 是的,我试过你的 jsfiddle。请参阅我添加了一个具有默认轮廓的 div。单击它一次,它的轮廓就永远消失了。 jsfiddle.net/RuHNW/1
  • 啊,我明白你的意思了。我修改了fiddle 并编辑了我的答案。看看这是否适合你,谢谢!
  • 这对我有用,我正在寻找一种方法来做到这一点......投了赞成票。
【解决方案2】:

我能看到的一种简单方法是使用鼠标事件来防止焦点触发。

$('#element').click(function(){
   $(this).blur();
});

这带来了一个潜在的问题,即您根本无法使用鼠标选择元素。所以你也可以只添加一个类并调整焦点样式。

$('#element').click(function(){
   $(this).addClass('fromMouse');
});
$('#element').blur(function(){
  if($(this).hasClass('fromMouse'){
     $(this).removeClass('fromMouse');
  }
});

CSS

.fromMouse{
  outline: none;
}

http://api.jquery.com/blur/

【讨论】:

    【解决方案3】:

    http://jsfiddle.net/np3FE/2/

    $(function(){
        var lastKey = new Date(),
            lastClick = new Date();
    
        $(document).on( "focusin", function(e){
            $(".non-keyboard-outline").removeClass("non-keyboard-outline");
            var wasByKeyboard = lastClick < lastKey
            if( wasByKeyboard ) {
                $( e.target ).addClass( "non-keyboard-outline");
            }
    
        });
    
        $(document).on( "click", function(){
            lastClick = new Date();
        });
        $(document).on( "keydown", function() {
            lastKey = new Date();
        });
    
    
    });
    

    CSS

    *:active, *:focus {
        outline: none;
    }
    
    *:active.non-keyboard-outline, *:focus.non-keyboard-outline {
        outline: red auto 5px;
    }
    

    【讨论】:

    • +1 表示唯一的 lastClick 和 lastKey 事物。但它看起来有点太长了。
    • @RakeshJuyal 好吧,它可以通过删除空格和合并事件来缩短很多,但这并不意味着它会更具可读性或更好:P
    • 最后一次点击和关键的事情似乎是解决这个问题的好方法。但是您需要挂钩 mousedown 事件而不是 click 才能更好地工作(至少在 Chrome 中)。
    【解决方案4】:

    CSS

    :focus{
      outline: none;
    }
    
    .outline{
      outline: 2px solid rgba(200,120,120, 0.8);
    }
    

    jQuery 代码

    $(function(){
      $('*').on('keydown.tab', function(e){
        /*
        TAB or Shift Tab, Aw.
        Add some more key code if you really want
        */
        if ( 9== e.which && this == e.target ){
          window.setTimeout( function(){
            $('.outline').removeClass('outline');
             $(document.activeElement).addClass('outline');
          }, 100 );
        }
    
      });
    
    });
    

    这很好用。只有当元素使用键盘聚焦时,你才会得到轮廓(我只知道 Tab 和 Shift Tab,你可以添加更多)

    看看效果: http://jsbin.com/okarez/1

    【讨论】:

    • 嗨@Rakesh Juyal,在上面的代码中,即使用户使用鼠标单击其他元素,上面的代码大纲仍保留在最后一个选项卡式元素上。在这种情况下如何去除轮廓?
    【解决方案5】:

    基于@theftprevention 的回答,一个更可定制的解决方案可以是:

    $(function(){
        $('body')
        .on('focus', '*', function() {
            var e = $(this);
            if (!e.is('.focus-mouse')) {
                e.addClass('focus-keyboard');
            }
        })
        .on('mousedown', '*', function() {
            $(this).removeClass('focus-keyboard').addClass('focus-mouse');
        })
        .on('blur', '*', function() {
            $(this).removeClass('focus-keyboard').removeClass('focus-mouse');
        });
    });
    

    现在,您只需在 CSS 中使用 .focus-keyboard 和 .focus-mouse 类进行自定义。

    .focus-keyboard{
        background:#eeeeee;
    }
    .focus-mouse{
        outline: 0;
    }
    

    【讨论】:

      【解决方案6】:

      删除outline 对可访问性来说太糟糕了!理想情况下,仅当用户打算使用键盘时才会显示对焦环。

      2018 年答案: 使用 :focus-visible。它目前是 W3C 提案,用于使用 CSS 设置纯键盘焦点样式。在主流浏览器支持之前,您可以使用这个强大的polyfill。它不需要添加额外的元素或更改tabindex

      /* Remove outline for non-keyboard :focus */
      *:focus:not(.focus-visible) {
        outline: none;
      }
      
      /* Optional: Customize .focus-visible */
      .focus-visible {
        outline-color: lightgreen;
      }
      

      我还写了一个更详细的post 和一些演示,以防您需要更多信息。

      【讨论】:

        【解决方案7】:

        如果用户当前正在使用鼠标或键盘,您可以将类添加到 body 以了解 css

        document.body.addEventListener('mousedown', function() {
          document.body.classList.add('using-mouse');
        });
        document.body.addEventListener('keydown', function() {
          document.body.classList.remove('using-mouse');
        });
        

        在css中

        :focus {
          outline: #08f auto 2px;
        }
        
        body.using-mouse :focus {
          outline: none;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-04-17
          • 2012-02-29
          • 2023-03-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-09-07
          • 2021-09-30
          相关资源
          最近更新 更多