如何在<button>标记上仅通过制表符而不在单击时在CSS轮廓上显示轮廓?

时间:2019-01-08 08:06:18

标签: html css html5 css3

我们有一些用css样式的按钮,并有一些这样的图标:

enter image description here

此按钮具有默认的轮廓属性,因此每次单击该按钮时,它都有一个轮廓(铬蓝色):

enter image description here

要摆脱它,我们当然可以覆盖此属性,例如:

outline: none

但是,当我们依次浏览并到达此按钮时,它也没有任何轮廓,这对于可访问性来说是一个不好的做法。

我们能否实现这一点,以便仅在带有选项卡的按钮上出现此轮廓,而在单击它时不出现?

仅作为信息:我们还有一些 a 标签,这些标签在外观上看起来像这样,并且通过标签,我们可以精确地实现所需的这种行为,只有当我们点击该链接时,轮廓才会出现,但不能点击。我们只希望按钮标签也具有完全相同的行为。

6 个答案:

答案 0 :(得分:6)

当您单击某个元素时,它会在其上投射:active,因此您想将:active:focus链接在一起:

button:active:focus {
  outline: none;
}
<button>Button</button>

正如您所说的,这不适用于其他CSS,在这种情况下,您必须实现一个有点复杂的解决方案,即在用户第一次使用Tab时在正文中添加类,否则一起删除轮廓

function handleFirstTab(e) {
    if (e.keyCode === 9) { // the "I am a keyboard user" key
        document.body.classList.add('user-is-tabbing');
        window.removeEventListener('keydown', handleFirstTab);
    }
}

window.addEventListener('keydown', handleFirstTab);
body:not(.user-is-tabbing) button:focus {
  outline: none;
}

button {
    background-color: red;
}
<button>Button</button>

答案 1 :(得分:1)

<块引用>

我们能否做到这一点,以便仅在我们使用带有选项卡的按钮出现时才显示此轮廓,而在单击它时不显示?

是的,您可以使用 :focus-visible

如果您希望在按钮被标签化且未被点击时显示轮廓,请在 outline: none 上的按钮上设置 :focus 而不是在 :focus-visible 上:

button:focus:not(:focus-visible) {
  outline: none;
}

答案 2 :(得分:0)

如果您的图标是某种字体,则最好的选择是使用Traceback (most recent call last): 30: from bin/rails:4:in `<main>' 29: from /Users/username/project/vendor/bundle/ruby/2.5.0/gems/activesupport- 5.1.0/lib/active_support/dependencies.rb:292:in `require' 28: from /Users/username/project/vendor/bundle/ruby/2.5.0/gems/activesupport- 5.1.0/lib/active_support/dependencies.rb:258:in `load_dependency' 27: from /Users/username/project/vendor/bundle/ruby/2.5.0/gems/activesupport- 5.1.0/lib/active_support/dependencies.rb:292:in `block in require' 26: from /Users/username/project/vendor/bundle/ruby/2.5.0/gems/bootsnap- 1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:29:in `require' . . . . 58:in `load_dependency' 1: from /Users/username/project /vendor/bundle/ruby/2.5.0/gems/activesupport- 5.1.0/lib/active_support/dependencies.rb:292:in `block in require' /Users/username/project/vendor/bundle/ruby/2.5.0/gems/bootsnap- 1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require': cannot load such file -- active_storage/engine (LoadError) gemfile ruby '2.5.1' gem 'rails', '5.1.0' gem 'mysql2', '>= 0.4.4', '< 0.6.0' gem 'puma', '~> 3.11' gem 'sass-rails', '~> 5.0' gem 'uglifier', '>= 1.3.0' gem 'jbuilder', '~> 2.5' gem 'bootsnap', '>= 1.1.0', require: false group :development, :test do gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] end group :development do gem 'web-console', '>= 3.3.0' gem 'listen', '>= 3.0.5', '< 3.2' gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' end application.rb require "rails" # Pick the frameworks you want: require "active_model/railtie" require "active_job/railtie" require "active_record/railtie" require "action_controller/railtie" require "action_mailer/railtie" require "action_view/railtie" require "action_cable/engine" require "sprockets/railtie" # require "rails/test_unit/railtie" # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. Bundler.require(*Rails.groups) module Project class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. config.load_defaults 5.2 # Settings in config/environments/* take precedence over those specified here. # Application configuration can go into files in config/initializers # -- all .rb files in that directory are automatically loaded after loading # the framework and any gems in your application. # Don't generate system test files. config.generators.system_tests = nil end end

text-shadow
button {
  outline: none!important;
  background: transparent;
  border-color: transparent;
  color: red;
  font-size: 30px;
}

button:focus i.fa {
  text-shadow: 1px 1px 5px rgba(255, 0, 0, 0.7);
}

在此示例中,我使用font-awesome-4.7并用text-shadow generator生成了<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <button class="btn"> <i class="fa fa-heart-o"></i> </button>

答案 3 :(得分:0)

使用.btn:focus{ outline:0; }删除outline

并使用addEventListener定位Tab点击并设置box-shadow(如果元素上的标签为

document.addEventListener('keydown', function(e) {
var elem=document.getElementById('heart');
  if (e.key === 'Tab' &&  document.activeElement === elem) {
     elem.style.boxShadow="0 0 0 0.2rem rgba(0,123,255,.25)";
  }
else{
elem.style.boxShadow="none";
}
  
});
.btn {
  width: 80px;
  height: 80px;
  transform: rotate(-46deg);
  border: none;
  background: url(https://image.flaticon.com/icons/svg/579/579268.svg);
}
.btn:focus{
outline:0;
}
<button class="btn" id="heart">
</button>

您可以使用此插件通过{strong> css 定位tab点击:https://github.com/ten1seven/track-focus

body[data-whatinput="keyboard"] .btn:focus {
  box-shadow:  0 0 0 0.2rem rgba(0,123,255,.25);
}

答案 4 :(得分:0)

由于上述所有答案在所有情况下均不适用于我(大多数情况至少忽略了一个事实,那就是人们可以再次切换到鼠标,然后必须从按钮中删除boxshow。)总是从事件侦听器中删除),这是我的答案:

如果您的html标记或多或少处于同一级别(因此您不必为整个页面创建侦听器):

  • 上一个元素(其“选项卡”应将焦点切换到按钮)应该具有keydown / keyup事件,然后该事件将运行:

    if ($event.keyCode === '9' && !$event.shiftKey) {
      $event.target.nextSibling.style.boxShadow = '0 0 5px 1px #305C73';
    }
    
  • 当您还希望支持shift + tab(后退制表)时,下一个元素也需要此功能:

    if ($event.keyCode === '9' && $event.shiftKey) {
      $event.target.previousSibling.style.boxShadow = '0 0 5px 1px #305C73';
    }
    
  • 按钮本身显示通过其自身的模糊事件将其删除:

    $event.target.style.boxShadow = 'none';
    
  • 按钮本身仍可以将其轮廓设置为无:

    outline: none
    

由于我在后台提出了独立于JS技术的问题,因此这里不包括事件处理部分。但是如果是有角度的应用,则可以使用sth。像这样:

<previousTag (keydown)="addBoxShadowBorButtonOnTab($event)">

<button (blur)="removeBowShadow($event)">

<nextTag (keydown)="addBoxShadowBorButtonOnShiftTab($event)">

在普通的javascript中,这部分的操作类似于上述事件监听器中的操作。

如果您的标签位于其他标签内,并且您具有分层的DOM结构,或者您无法更改“上一个”和“下一个”标签:

就我而言,我们有……。像这样:

<li>
  <previousTag>
  <button>
</li>
<li>
  <nextTag>
<li>

最好注册用于添加boxShadow的keyup / keydown事件的侦听器,因为这样您将更独立于HTML结构和将来的DOM更改。因此,您可以设置轮廓,而与来自哪个元素无关。

在我的Angular应用中,似乎……。像这样:

  @HostListener('document:keyup.shift.tab', ['$event'])
  @HostListener('document:keyup.tab', ['$event']) onTabHandler(event: KeyboardEvent) {
    const focusedElm = event.target;
    if (focusedElm.id === 'my-heart-button') {
      focusedElm.style.boxShadow = '0 0 5px 1px #305C73';
    }
  }

删除轮廓仍应与上述完全相同。

这是确保按钮“总是在分页时集中注意力”时始终具有轮廓的唯一方法,但不会在涉及美观的鼠标单击上出现。

答案 5 :(得分:0)

我找到了一个简单的方法,那就是纯 html/css 并且不使用任何 javascript。

  1. 将按钮的内容包装在额外的外部元素(例如 div)中,并使用 tabindex="0"

    使包装器可聚焦/可制表
  2. 内部元素得到tabindex="-1"

所以代替:

<button>Buttontext</button>

这样做:

<div tabindex="0">
    <button tabindex="-1">
        Buttontext
    </button>
</div>

通过这种方式,您可以在外部 div 上使用 Tab 键,浏览器会绘制其焦点轮廓。当您点击按钮时,您选择了没有轮廓的内部元素 (outline: none)