【问题标题】:Can you make :after styling dependent on the element value?您可以根据元素值制作 :after 样式吗?
【发布时间】:2019-01-17 19:47:53
【问题描述】:

我想对数字输入字段做一些动态样式,所以我把它放在一个 span 元素中,这样我就可以添加非数字字符:

<span class='formatter'>
    <input type='number'>0.00</input>
</span>

然后,在css中:

.formatter:after {
    position: absolute;
    content:"%";
    top: 12px;
}

这可行,% 出现,但我希望它出现在输入值之后。所以,我可以使用 left: 200px;将 % 推到输入字段的末尾,但我希望它出现在数字本身之后,无论是 0.00 还是 100.00。有没有办法将内容位置与输入值联系起来?

【问题讨论】:

    标签: javascript html css angularjs


    【解决方案1】:

    首先,您的标记无效:&lt;input&gt;void tag
    你可能想使用placeholder attribute:

    <input placeholder="0.00%">
    

    至于掩蔽,它并不像看起来那么容易。您可以编写自己的指令,但需要考虑以下几点:

    • 如果您想在其中显示非数字(和与数字相关的字符),您的输入必须是 type="text" 而不是 number

    或者你可以只使用 angular-input-mask 包,它是为屏蔽 angular.js 中的输入而设计的:

    <input type="text"
           placeholder="0.00%"
           ng-model="number" 
           ui-percentage-mask="2" 
           ui-percentage-value
           ui-hide-space
    >
    

    工作示例:

    var app = angular.module('app', ['ui.utils.masks']);
    app.controller('testController', ['$scope', function($scope) {
      $scope.number = 100;
    }])
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-input-masks/4.2.1/angular-input-masks-standalone.min.js"></script>
    
    <div ng-app="app" ng-controller="testController">
      <input type="text"
             placeholder="0.00%"
             ng-model="number" 
             ui-percentage-mask="2" 
             ui-percentage-value
             ui-hide-space
       >
     </div>

    缺点是当您输入20 时,因为您需要2 个小数,您需要输入2000,但这有点直观。


    或者,您可以将其与范围输入结合使用,以提供更友好的用户体验。我还与听众玩了一些,以提供更多type="number" 的感觉,但您可以完全放弃它:

    app = angular.module('app', ['ui.utils.masks']);
    
    /* 
     * You don't really need any of the controller code below. 
     * I just fooled around binding keydown events to experiment making 
     * the input[type="text"] feel more like [type="number"].
    
     * If you don't want it, simply use...
    
    app.controller('testController', () => [])
    
     * ... or delete it altogether and remove `ng-controller`
     * attribute from [ng-app] element.
     */
    
    app.controller('testController', ['$scope', '$element', '$timeout', function($s, $e, $t) {
      this.$onInit = function() {
        // binding $scope.number changes on up/down/pageUp/pageDb
        $e.on('keydown', 'input', (e) => {
          if ([38, 40, 33, 34].includes(e.keyCode)) {
            e.preventDefault();
            e.stopImmediatePropagation();
            if ([38, 40].includes(e.keyCode))
              $s.number += e.keyCode === 38 ? .1 : -.1;
            else
              $s.number += e.keyCode === 33 ? 1 : -1;
            $t(() => $s.$apply());
            return false;
          }
        })
      };
    }]);
    input-wrapper {
      position: relative;
    }
    input-wrapper [type="text"]{ 
      font-size: 2rem;
    }
    
    input-wrapper [type="range"] {
      position: absolute;
      top: calc(100% - .5rem);
      left: -2px;
      width: 100%;
      opacity: 0;
      padding: 1rem 0;
      transition: opacity .25s cubic-bezier(.5, 0, .3, 1);
    }
    
    input-wrapper:hover [type="range"],
    input-wrapper input:focus~[type="range"],
    input-wrapper input:active~[type="range"],
    input-wrapper [type="range"]:focus,
    input-wrapper [type="range"]:active {
      opacity: 1;
    }
    
    input-wrapper [type="text"] {
      position: relative;
      z-index: 1;
    }
    
    p {
      padding-top: 1rem;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-input-masks/4.2.1/angular-input-masks-standalone.min.js"></script>
    
    <div ng-app="app" ng-controller="testController">
      <input-wrapper>
        <input type="text" placeholder="0.00%" ng-model="number" ui-percentage-mask="2" ui-percentage-value ui-hide-space>
        <input type="range" ng-model="number" min="0" max="100" step="0.01">
      </input-wrapper>
      <p>Use Up/Down/pageUp/pageDn on a focused input
    </div>

    如果你觉得style the range slider cross-browser 很困难,有很多包提供样式化范围滑块,其中一些是可定制的。

    【讨论】:

    • 感谢您的指导和示例 - 非常好。我会深入研究一下,看看我能想出什么。
    【解决方案2】:

    我会放弃 css :after 属性并编写如下内容:

    <div class="formatter">
        <input type="number" ng-model="$ctrl.number">0.00</input>
        <span ng-if="$ctrl.number <= 100" class="pretty_percentage">%</span>
    </div>
    

    然后自定义pretty_percentage css。

    【讨论】:

    • 自定义过滤器也很适合这里。
    • @Phix 我愿意试一试,虽然我以前从来没有做过...你能举个例子说明一下吗?
    • @monkeyWithAMachinegun 当然,请查看the docs,如果遇到任何问题,请报告。
    • @Phix 我尝试了过滤器,它有点工作......如果我能弄清楚我做错了什么,这将是一个很好的解决方案。这些 HTML 元素是动态创建的,所以我做了类似的事情(其中 'elem' 是新创建的输入元素): elem.innerHTML = '{{ '+thevalue+ ' |货币 }}'。当它运行时,它只显示一个数值(本例中为 100),但如果我进入浏览器控制台,我可以看到它显示为 $100.00。所以看起来过滤器被应用了,但我一定是错误配置了一些东西。也许 innerHTML 是设置错误的值?
    • 新建一个问题,不能用innerhtml设置。还有其他可用的机制。
    猜你喜欢
    • 2010-12-12
    • 2012-11-13
    • 2015-10-30
    • 1970-01-01
    • 1970-01-01
    • 2021-03-19
    • 2019-10-15
    • 2014-01-28
    • 1970-01-01
    相关资源
    最近更新 更多