Taking Advantage of Debugging Tools for Android App Development

Hello! I'm Joseph and I'm an Android engineer from the Mobile Infrastructure team.

In this post, I will talk about some of the tools that we used in debugging while working on the renewal project. The contents of this post were presented in the recently held Tech Kitchen #25.

Renewal Project

As mentioned in the article テストケース作成を仕様詳細化の手段とする実験 published earlier this year, the Cookpad app for iOS has undergone a lot of changes as part of the renewal project.

Last October, it was Android's turn and we published the Cookpad app for Android which underwent a similar renewal project. Since this is a fairly large project, it's quite challenging to develop and debug. However, we used some tools that helped us improve our workflow.

Flipper

f:id:epishie:20201223161236p:plain

Some time ago, Facebook published a tool called Stetho, a debug bridge tool build for Android using Chrome Developer Tools. Stetho is quite useful but the functionality is limited and the client is dependent on Chrome. In 2018, they released Flipper to replace Stetho and now works on iOS, Android and ReactNative apps and with its own stand-alone client built on Electron.

Flipper has two components, the app SDK which is added as a dependency to the target app, and the desktop client where users can interact and view the data sent from the app via the SDK. Out-of-the-box, Flipper includes some core plugins users can use right away to inspect various app components with minimal setup but developers can also extend it and add or publish their own plugins.

Layout Inspector

f:id:epishie:20201223161654p:plain

One of the core plugins is the Layout Inspector. This is very useful in debugging complex UI especially when screen content is obtained from an API or user-generated like some of the screens that we've added in the renewal project.

Using Flipper, the view tree of the screen can be checked and verified if the views are inflated correctly.

Client App
f:id:epishie:20201223161759p:plain:w480 f:id:epishie:20201223161806p:plain:w160

Selecting the view will reveal the view attributes, which can be updated while running the app without recompiling or restarting. Hovering on the view will highlight the said view within the app running on the device or on the emulator. It also shows within the app the view bounds and margins or paddings if the view has it. This is very useful not only for developers during debugging but also for designers when verifying the design specs. There's a lot of other features like view search and target mode so please check the documentation for more information.

Network Inspector

f:id:epishie:20201223162344p:plain

Network Inspector is also one of the core plugins. Using this tool, HTTP requests sent from and responses received by the app can easily be verified. Out-of-the-box, the Network Inspector plugin can be integrated with OkHttp as an Interceptor that can be added to the client. Since the inspector is added directly to the HTTP client, even HTTPS requests can be inspected without dealing with encryption and certificates. For clients other than OkHttp, integration code can be written by calling the appropriate methods of the SDK's network plugin object. Recently, they added the Mock feature to stub HTTP responses which is very helpful during debugging.

Shared Preferences Viewer

f:id:epishie:20201223163054p:plain:w320

Another core plugin is the Shared Preferences Viewer. In the Cookpad app, there's a custom component called Spotlight that we use when onboarding users to the features that were added in a release. This component consists of a custom view to highlight the new feature and a SharedPreference key-value to keep track of whether the user has been shown the onboarding or not.

f:id:epishie:20201223163245p:plain

Since onboarding is a one-off event, it requires deleting the app storage (SharedPreferences) to re-test and debug. With the Shared Preferences Viewer, instead of clearing the app storage, the actual key-values can be verified and modified while running the app to modify the behavior.

These are just 3 of the core plugins that we use during development. There are other plugins like the Databases plugin for inspecting local SQLite databases, and Images plugin for monitoring image loading using third-party libraries like Fresco.

Hyperion

Hyperion is a plug-and-play debug menu library designed to help fill in the gaps between design, development, and QA. By adding the library as a dependency to the Android project, usually for debug configuration only, the menu can be accessed while running the app by shaking the device or through the notification drawer.

f:id:epishie:20201223163307g:plain:w320

Hyperion includes a variety of core plugins each serving a different function. Like Flipper, Hyperion also supports custom plugins developers can add to support different use-cases.

Over the years, we've created our own custom Hyperion plugins to assist in debugging and verifying the app behavior.

Drawer Other Tools
f:id:epishie:20201223163435p:plain f:id:epishie:20201223163453p:plain

During the renewal project, some tools were created as needed to specifically help debug the new features that we were adding to the app.

Button Style Verification

Before starting to work on the renewal project, to be able to use the new Material Design components, we had to migrate from the AppCompat theme to the MaterialComponents theme. Since the project already had a lot of custom button styles declared used within the app, we were afraid existing UI design might break when changing the theme.

f:id:epishie:20201223163547g:plain:w320

Instead of checking each screen for each button style, we built a simple tool where designers can see a preview of all the button styles in a single screen. This is a very simple tool but it definitely cut the time that it takes between designers' feedback and bug-fixing.

Ken Burns Preview

f:id:epishie:20201223163618g:plain

In some of the the screens that we're added during the renewal project, series of images are shown in a slideshow with fade-in/fade-out transitions and custom animations which are called Ken Burns Effect.

The effect patterns are designed to be random, and depend on the number of images to be shown and whether there's a video included. Since this feature is already implemented in out Cookpad iOS app, the actual tweaking of the effect parameters were already done as discussed in detail in this post.

f:id:epishie:20201223163753g:plain:w320

However, designers still need to verify that the effects are played correctly and are the same as the iOS version. Testing on the actual screen is unreliable since the effects are dependent on randomness and the count and type of content. To help designers verify the feature quickly, we built this tool where they can check the effects, change the patterns and verify the effect with different combination of contents.

Quick Navigation

f:id:epishie:20201223163850p:plain:w320

During the renewal project, we were adding new features that has a set of list and details screens. Most of the time, these screens are implemented independently and simultaneously and sometimes by different developers. Because of the parent-child relationship of the screens, the actual navigation between the screens cannot be implemented until the set is completed. To allow such navigation during development, we built a simple navigation list screen so that it's possible to access the child screens.

Log Viewer

As with most apps these days, in the Cookpad Android app, we do record logs of user's actions which are useful in analyzing and understanding the status of our services. Since these logs are buffered before being sent to our log infrastructure, when adding logs to the app, to make sure that the implementation is correct, we had to wait for the logs to be printed in logcat and/or check the backend.

f:id:epishie:20201223163909p:plain:w320

To speed-up the development and debugging, we've added a simple Log Viewer tool. Since our logging library called Puree allows adding filters that can be applied to each log before sending, we created and added a filter where we can record the logs to a local database which the Log Viewer can query and display as a list.

Demo Apps

f:id:epishie:20201223163938p:plain:w320

The Cookpad Android project was split into feature modules for better code organization and cohesion, and to potentially improve the time it takes to build and run the app. However, even if the features are independent of each other, debugging and verification still involves the whole project and the whole app has to be built and run.

The Cookpad iOS app has the Sandbox apps which are mini-apps that contain a single feature that depends only on a subset of the app's modules. For Android we built a similar mechanism called Demo apps.

f:id:epishie:20201223164015g:plain:w320

With Demo apps, it's possible to build only the modules needed for a feature and provide a simple entry point for the screens a feature has instead of building and running the whole app. The details of how Demo apps are implemented in Android are described in this post.

Final thoughts

We all know that developing large projects like the Android renewal project is difficult. Debugging and testing of projects with large and complex feature set are even harder. However, in most situations, there are tools already available to address some of the pain points we encounter during development. In situations in which there's no tool yet, why not try creating one. If you do, you might want to share it so that everyone can use it too.

【開催レポ】Cookpad Tech Kitchen #25 日本最大レシピサービスのモバイルアプリ開発事情

こんにちは。クリエイション開発部の星川 (@star__hoshi) です。
2020年12月10日に Cookpad Tech Kitchen #25 日本最大レシピサービスのモバイルアプリ開発事情 を開催しました。今回は新型コロナウイルスの影響もありオンラインでの開催となりました。

f:id:star__hoshi:20201217101301p:plain

クックパッドには多くのレシピが投稿され、利用者数も多いサービスとなっています。その規模の大きさから、サービスの改善には事業的にも技術的にも独自の困難がつきまといます。

  • コードの品質はどう保つか
  • 日々の業務効率を高めるために使えるツールはあるか
  • ログを始めとした技術基盤をどう整備するか
  • その基盤を活かしてどのようにサービスを開発していくか

今回はモバイルアプリの領域にフォーカスし、このような課題に日々立ち向かっている吉田、ジョセフ、三木、星川の4名が、日々の業務を通して得た知見について発表しました。

発表内容

「基本のAndroid View開発ドキュメント」/ 吉田 万輝 (@_k4zy)

クックパッドではAndroid開発経験やプロジェクトへ関わる期間が様々な人々がいる状況でチーム開発を行っています。
Android開発を効率的に進めるため「誰が書いても大体同じような実装になる」ことを目指し、モバイル開発基盤が主導して整備している開発方針のドキュメントについて発表しました。

基本の Android View 実装ドキュメントの紹介 にも詳しい記載があるので、合わせてお読みください。

「Efficient app development using various debugging and verification tools(デバッグや検証ツールを活用した効率的なアプリ開発)」 / Joseph Iturralde

Androidアプリのリニューアルプロジェクトに伴い、開発効率改善のために様々なツールを利用したり、また必要に応じてツールを作成しました。
その時に役立ったツール、テクニック、デバッグ手法やビルドの高速化について紹介しました。

「モバイルアプリ行動ログ基盤を”大統一”した話」/ 三木 康暉 (@giginet)

モバイルアプリ上でユーザーの行動ログを記録する際、従来の方法では、仕様の共有や、ミスを防ぐのが難しいという問題がありました。
この発表では、ログのドキュメントから、モバイルアプリの実装を自動生成することで、安全なログ基盤を高速に構築した事例を紹介しています。

ドキュメントベースの型安全なモバイルアプリ行動ログ基盤の構築 に記事がありますので、合わせてお読みください。

「大統一ロガーを利用したサービス開発」/ 星川 健介 (@star__hoshi)

giginet の発表した「大統一ロガー」によって、ログ基盤が整えられました。
その大統一ロガーはサービス開発者にとってどういうメリットがあるのか、また大統一ロガーを利用してどのようにクックパッドのiOSアプリを改善しているか紹介しました。

Q&A

オンライン開催のため、ZoomのQ&A機能を使いたくさんの質問をいただきました。そのうちのいくつかをピックアップして紹介します。

ConstraintLayout を使うとあらゆる View に id 名をつけると思いますが、id名の命名規則はどのようにしてますか xxxxText なのか textXxxx なのかとか

実はidの命名規則は決めてないのですが圧倒的に xxxxText が多数派です。
とても良いご指摘なのでidの命名規則もドキュメントに記載して統一しようと思います。

ログ定義はプラットフォーム間で共有されていますか?

大統一ロガーに関して、ログ定義はプラットフォーム間で共有されていません。
アプリケーションごとに画面構成が違ったり、ログの要件も違う場合があるので分離しています。

これは、過去の行動ログ基盤の運用を通し、複数のプラットフォームのログを統合すると、デメリットの方が多かったという経験に寄るものです。

ログをみてから仮説を得ることと仮説を確認するためにログをとることのどちらの方が多いですか? また、気になったことをいちいちログとりしていくの大変(=面倒くさい)ではないですか?

ログを見てから仮説を得ることもありますし、仮説を確認するためにログを取ることのどちらもあり、どちらが多いというのは難しいです。
気になったことをいちいちログ取りしていくのは大変ですが、施策を実施する前に「どの指標がどれくらい伸びたら成功とする」というのを決めることが多く、ログの取得はほぼ必須となっています。

感想

オンラインの開催となり、参加者が少なくならないか、質問があまり来ないかもと不安な中でのスタートでしたが、たくさんの方に参加いただき質問もたくさんいただきました。
Android/iOS共にアプリのリニューアルを行い、そこでの知見を発表させていただきました。Markdown でログ定義を作成しそこからロガーのコードを生成すると決定したときは「マジか、yml とかで定義書いてそこからドキュメントとコード生成した方がいいんじゃないか…」と思ったんですが、実際に運用してみると Markdown は書きやすいしすぐにプレビューも出来てとても便利でうまく回っています!

最後に

クックパッドでは、モバイル基盤部とサービス開発の部署が連携して開発しています。
クックパッドのモバイルアプリ開発やサービス開発について、もっと聞いてみたい、ディスカッションしたいという方がいらっしゃいましたら、個別雑談会も実施しているので是非お申し込みください! カジュアルに情報交換しましょう!
お申し込みはこちら → https://enq.cookpad.com/meet_cookpad_engineer

モバイルアプリの開発上の違和感・痛みに向き合い、少しずつでも前進するための取り組み

こんにちは、モバイル基盤部の茂呂(@slightair)です。 いやー12月になって寒くなってきましたね。

この記事では最近部で始めた「アーキテクチャ課題共有会」という取り組みについて紹介したいと思います。

開発中に感じる痛み

いきなりですが、モバイルアプリの開発中に痛みを感じたり違和感を持ったことはありませんか? 痛みというと大げさかもしれませんが、例えば以下のような設計・実装上のつらみ、悩みのタネたちのことを指します。

  • 同じような記述を毎回書く必要がある
  • 採用している設計パターンにあてはめようとすると、実装しづらい場合がある
  • 必要となる場面が多い割にできないことがある
  • 適切に扱うのが難しく、使い方を間違えやすいものがある
  • 複雑で理解するのが難しい、手を入れられない

特に複数人で開発しているアプリプロジェクトだと、自分でそういう痛みを感じることもあれば、他の人からそういう声が聞こえてくるという経験があるんじゃないかと思います。

僕たちが開発しているクックパッドアプリはサービスがリリースされてからずっと開発を続けているので、その間に開発規模や環境が大きく変わっています。 例えば、以下のものが挙げられるでしょう。

  • 開発人数・規模の増加
  • 人の入れ替わり
  • サービスのリニューアル
  • アーキテクチャの変更
  • モジュール分割などによるアプリ構造の変化

また、社内だけでなく、OSの更新、プラットフォームの進化、開発ツールの進化など、外部の要因もありますね。

そのような環境の変化があるたびに、それに合わせたやり方や仕組みの見直しを行うわけですが、導入した方針や仕組みがいつも最適な選択であるとはかぎりません。 最初は良さそうに思えたものであっても、使っているうちに欠点に気がついたり、状況が変わって適さなくなったものが出てきます。そうしたものが違和感や痛みとして表面化してきます。

痛みに気づいたら整理して解消すればよい

開発環境には変化が起こり続けているので、このような痛みや違和感が出てくるのは当然のことです。気づいたら課題を整理して解消していけばよいでしょう。

このような痛みに気づいて解消していくためには、どんな些細なことでもよいので、なにか思うところがあったら声を上げやすい雰囲気づくりが大切だと思います。幸いにもクックパッドのアプリ開発の現場ではそのような空気ができているように感じています。

Slack など普段会話をしているところで「こういうところつらくない?」というコメントが流れると「それな」「わかる」「オアーッ!」というようなリアクション*1も一緒に集まってきます。 丁寧な人であれば具体的に困っている設計上の課題や仕組みについて issue に書いてくれる場合もあります。

f:id:Slightair:20201215142521p:plain
Slack での会話

気づいて声を上げるところまではよいのだが…

痛みに気づいた人の声をきっかけに議論がはじまり、具体的な解決案がすぐにまとまればよいですが、必ずしもそのようにスムーズに話が進むわけではありません。 ほとんどの場合、大筋の合意を取って修正の方針を決めるまでが難しく、時間がかかります。

そのため、新しい課題が出てきても普段の仕事をたくさん抱えている中では、致命的なものでない限りなかなか向き合えないことがあります。 今までのやり方でも進められる場合は、違和感を持ちながらもそのまま進めることができてしまうからです。 すると、良くない部分に気づいているのにその問題が埋もれていってしまい、改善が進まないという状況になってしまいます。

最近でいうと、モジュール分割*2に関連する実装上の悩みや、アーキテクチャ*3についての課題が多く出ていました。仕組みの導入や整理した後に、それを実際に使ってサービス開発を進めることではじめて見えてくる問題点はたくさんあります。

部内の乗り越えたい課題

僕の所属するモバイル基盤部は、クックパッドでのモバイルアプリの開発環境を整えるという責務を担う部です。 サービス開発が円滑に進むようにクックパッドアプリの中核部分をメンテナンスしたり、設計パターン、実装方針の決定を主導するということが業務に含まれます。

部には、古くからクックパッドアプリの開発に関わっていて現状の実装方針の経緯に詳しい人もいればそうでない人もいます。 また、画面構築やモバイルアプリの設計パターンの知識、それらに対する興味・関心、得意不得意も人それぞれです。

そのため、改善の業務を進める上で部にもいくつか乗り越えたい課題がありました。

  • 現状のアーキテクチャや実装がどういう状態になっているのか、全員が認識している状態になる
  • 実際に基盤のツールやアーキテクチャを利用した際のサービス開発時の問題点を把握し、理解できるようになる
  • 現状認識の統一を図り、改善の方向性の意思統一ができるようになる

これらの課題は、アサインされたモバイル基盤部の業務を単純に遂行するだけでは落としやすいものばかりです。 浮かび上がってくる課題の理解を深め、真摯に解決に取り組み改善を進めていけるようなフローが必要だと考え始めました。

課題をきちんと拾って向き合う時間を作ろう

せっかく上がってきた課題や意見が Slack コメントや issue のままそこで止まらないように、定期的にきちんと課題に向き合う時間を作って運用してみることにしました。 前述の通り、アプリのアーキテクチャに関する話題が多かったので「アーキテクチャ課題共有会」という名前で始めています。

とりあえず以下のようなルールで始めてみました。

  • アプリのリポジトリとは別に、設計上の課題のみが集まるリポジトリを作り管理する
  • 毎週30分、ひとつ課題をとりあげて背景の理解とその解決方法について議論する
  • 参加者持ち回りで、課題の整理と可能であればその解決案を考えて事前にまとめてきてもらい、課題共有会の最初に説明してもらう
  • 議論中別の話題に発展したら、次回以降につづけるようにする
  • 対応方針が決まったら、やるだけの状態になるのでアサインする

このやり方で 2,3ヶ月運用してみて、うまく回っているところと改善できそうなところの両方がありますが、すでにいくつかの課題の解決に役立てる事ができています。

実際に上がってきた課題の例と課題共有会での進行

この期間で上がった課題の例をひとつ挙げると、「ユーザ情報を表現するオブジェクトの取得方法とその扱いがイマイチ」というものがありました。 この課題をテーマに議論することになりました。

アプリの機能や画面表示において、ログインしているかどうか、有料会員かどうかなどのステータスに依存するものはとても多いです。 このようなユーザ情報を取得したいケース、その使い方を整理して、イマイチな部分を改善しようということになりました。

事前準備

その回の担当者は事前に課題を以下のように整理してきました。

  • ユーザ情報の変化に追従する必要のある画面とそうでない画面があり、ほとんど後者である
  • 現状の仕組みでは全ての場面でユーザ情報の変化を意識しないといけない作りであり、複雑になってしまっている
  • モジュール分割の初期の仕組みに乗っているが、今は別の適切な実装手段があるので、新しい方法に乗り換えるべき

このような、現状とその問題点、それに対する解決案が参加者に共有された状態で議論を行います。 もしキャッチアップの段階で疑問点があれば、議論に入る前に解消します。

議論

課題の整理が済んだら提案された解決方法を評価したり、具体的な実装方法について話し合います。 議論中に別の課題が浮かんできたら元の議論が発散しないように注意し、次以降の課題共有会で話せるように内容を残しておきます。

この回では、ユーザ情報の変化を意識せずに各画面を実装するための仕組みの導入と、新しい実装手段への置き換えを行うことに決まりました。

方針の決定と導入

議論で修正方針が固まったら、どのような話が行われ、どのような結論に至ったかをまとめ、決定事項として残すようにします。 その決定事項をもとに、具体的な作業に落とした issue をアプリのリポジトリに作成するようにします。 あとは通常の修正と同じようにPRを作成し、レビューのステップを踏んで導入完了となります。

f:id:Slightair:20201215142621p:plain
課題共有会後の記録の例

課題共有会の良いところ、これから改善できそうなところ

アーキテクチャ課題共有会を始めたことで良かった点と今後の改善点を紹介します。

定期的に課題に向き合い、前に進めるようになった

まず、定期的に時間を取って課題に向き合うことにより、確実に前に進むことができるようになりました。 また、議題に上がった内容やそれに対して決めた「現時点の方針」をきちんと整理して残せるようになりました。

前述したように、開発環境や状況に応じて最適な戦略や方針は常に変わり続けるので、現時点で何を考えどういう方針を取ったのか記録として残るのが大切なところです。

毎週課題共有会を開いているので、方針が決まってあとはやるだけという状態のものがいくつも生み出せていますが、今度は決まったものの実装待ちが溜まりがちという問題も起きています。 前には進んでいるので今は一旦よしとしています。

参加者の負担を減らしつつ、個人の関心を高められる

課題共有会のはじめのキャッチアップをすばやく行うために、事前準備を行うようにしていました。 この準備はある程度手間のかかるものですが、持ち回りで準備をすることで、負担をうまく分散することができています。 負担の分散だけでなく、各個人で課題の深い部分に気づいたり意識をするようになって、議論を重ねるたびに話が進めやすくなる利点もありました。 また、長年の開発によって積もってきた実装方法や課題、歴史的経緯についても理解を深める機会にもなっています。

議論しているとあっという間に時間が過ぎてしまうので、なるべく小さい課題に分割してから議題として選ぶようにしていますが、それぞれの根となる課題は繋がっていることも多いのです。

アプリの設計方針、戦略についての意識合わせができる

当初の狙い通り、目線や今後の戦略についての意識合わせにも役立ちそうでした。 また、アプリ開発の知識量やアプリの経験値の埋め合わせにも効いています。

僕たちは自分たちのアプリの設計の議論からはじめてしまいましたが、もしモバイルアプリの設計パターンの知識が少なかったりメンバー間で大きく差がありそうな状況であれば、一般的な設計パターンの学習からはじめるのがよさそうにも思いました。 僕たちもこの取り組みを続けるうちにあまり良い答えが見つからなくなってきたら、途中で学習に切り替えようと思っています。

部の課題に関係したこともあり、基本的に今はモバイル基盤部のメンバーのみで課題共有会をやっていますが、取り上げる課題によってゲストを呼び、詳しい状況を聞いたり意見をもらったりしています。 アプリで採用する方針の決定にサービス開発者の現場の視点も入れた方が、より実際の利用に合った方針の選択が期待できるので、他の部署からの参加も呼びかけていきたいと思っています。

より形式的な課題管理の方法を試したい

課題共有会の取り組みはお試しだったため、ゆるーい運用ではじめてみましたが、段々と形になり始めているのでもう少し議題の選び方や粒度をしっかりしていけるとより有益な会にできそうと感じています。 情報の整理方法についても、何を書いて残すべきかはっきりするようなテンプレートを整備するなど、もっと形式的にやっても良さそうに感じています。 Issueのラベルで状態を示すようにしたり、いろいろな工夫をちょうど試しているところです。

まとめ

最近モバイル基盤部で始めた、アーキテクチャや開発環境に対する課題を共有し議論して前に進める取り組みについて紹介しました。 こうして書いてみると「課題を整理して時間を取って議論して記録を残そうね」という当たり前の部分が多く、チームによっては自然に行っていたプロセスかもしれませんが、やり始めてみたらしっくりはまってきたプロセスだったため、紹介しました。

このように様々な形でモバイルアプリ開発の環境を改善していきたいモバイルアプリエンジニアの方、またはこのような開発環境でクックパッドのサービス開発にじっくり取り組んでみたいモバイルアプリエンジニアの方がいましたら、ぜひご連絡ください。

*1:カスタム絵文字を作っておくと便利です

*2:〜霞が関〜 クックパッドiOSアプリの破壊と創造、そして未来 - https://techconf.cookpad.com/2019/kohki_miki.html

*3:2020年のクックパッドAndroidアプリのアーキテクチャ事情 - https://techlife.cookpad.com/entry/2020/11/17/110000

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('https://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('https://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/